mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-21 18:33:23 +00:00
bugfix: 修复smp启动的时候,损坏0号核心的idle进程的内核栈的问题 (#711)
--------- Co-authored-by: longjin <longjin@DragonOS.org> Co-authored-by: heyicong <heyicong@dragonos.org>
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
#include "../common/asm.h"
|
||||
#include <asm/apu_boot.h>
|
||||
|
||||
|
||||
.align 0x1000 // 按照4k对齐
|
||||
@ -112,9 +113,9 @@ _apu_code64_vector:
|
||||
.long _apu_code64 - _apu_boot_base
|
||||
.word 0x18,0
|
||||
|
||||
.align 0x1000
|
||||
_apu_boot_tmp_stack_start:
|
||||
// .org 0x400
|
||||
.align 0x1000
|
||||
ENTRY(_apu_boot_tmp_stack_start)
|
||||
.skip APU_BOOT_TMP_STACK_SIZE
|
||||
_apu_boot_tmp_stack_end:
|
||||
|
||||
ENTRY(_apu_boot_end)
|
||||
|
@ -3,6 +3,7 @@
|
||||
// 2022/01/20
|
||||
|
||||
#include "common/asm.h"
|
||||
#include <asm/apu_boot.h>
|
||||
|
||||
// 以下是来自 multiboot2 规范的定义
|
||||
// How many bytes from the start of the file we search for the header.
|
||||
@ -249,7 +250,6 @@ ENTRY(_start64)
|
||||
lidt IDT_POINTER(%rip)
|
||||
//lidt $IDT_POINTER
|
||||
movq GDT_POINTER(%rip), %r12
|
||||
movq head_stack_start(%rip), %rsp
|
||||
|
||||
// 分支,判断是否为apu
|
||||
movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu
|
||||
@ -257,6 +257,9 @@ ENTRY(_start64)
|
||||
bt $8, %rax
|
||||
jnc load_apu_cr3
|
||||
|
||||
// BSP处理器
|
||||
movq head_stack_start(%rip), %rsp
|
||||
|
||||
// 2. 设置临时页表
|
||||
// 最高级
|
||||
mov $__PML4E, %eax
|
||||
@ -318,11 +321,11 @@ load_cr3:
|
||||
load_apu_cr3:
|
||||
// 由于内存管理模块重置了页表,因此ap核心初始化的时候,需要使用新的内核页表。
|
||||
// 这个页表的值由smp模块设置到__APU_START_CR3变量中
|
||||
|
||||
// 加载__APU_START_CR3中的值
|
||||
movq $__APU_START_CR3, %rax
|
||||
movq 0(%rax), %rax
|
||||
movq %rax, %cr3
|
||||
movq _apu_boot_tmp_stack_top_addr(%rip), %rsp
|
||||
jmp to_switch_seg
|
||||
|
||||
to_switch_seg:
|
||||
@ -348,7 +351,21 @@ entry64:
|
||||
movq %rax, %gs
|
||||
movq %rax, %ss
|
||||
|
||||
movq head_stack_start(%rip), %rsp //rsp的地址
|
||||
// 分支,判断是否为apu,然后设置栈指针·
|
||||
movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu
|
||||
rdmsr
|
||||
bt $8, %rax
|
||||
jnc __set_ap_tmp_stack_start2
|
||||
__set_bsp_stack_start2:
|
||||
movq head_stack_start(%rip), %rsp
|
||||
jmp __set_stack_start2_ok
|
||||
__set_ap_tmp_stack_start2:
|
||||
// 设置ap核心的临时栈
|
||||
movq _apu_boot_tmp_stack_top_addr(%rip), %rsp
|
||||
jmp __set_stack_start2_ok
|
||||
|
||||
__set_stack_start2_ok:
|
||||
|
||||
|
||||
// 重新加载GDT和IDT,加载到高地址
|
||||
leaq GDT_Table(%rip), %r8
|
||||
@ -485,6 +502,9 @@ go_to_ignore_int:
|
||||
ENTRY(head_stack_start)
|
||||
.quad BSP_IDLE_STACK_SPACE + 32768
|
||||
|
||||
ENTRY(_apu_boot_tmp_stack_top_addr)
|
||||
.quad _apu_boot_tmp_stack_start + APU_BOOT_TMP_STACK_SIZE
|
||||
|
||||
// 初始化页表
|
||||
.align 0x1000 //设置为4k对齐
|
||||
__PML4E:
|
||||
|
2
kernel/src/arch/x86_64/include/asm/apu_boot.h
Normal file
2
kernel/src/arch/x86_64/include/asm/apu_boot.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#define APU_BOOT_TMP_STACK_SIZE 1024
|
@ -300,13 +300,14 @@ unsafe extern "C" fn do_general_protection(regs: &'static TrapFrame, error_code:
|
||||
""
|
||||
};
|
||||
kerror!(
|
||||
"do_general_protection(13), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}
|
||||
"do_general_protection(13), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t rflags: {:#x}\t CPU: {}, \tpid: {:?}
|
||||
{}{}{}
|
||||
Segment Selector Index: {:#x}\n
|
||||
",
|
||||
error_code,
|
||||
regs.rsp,
|
||||
regs.rip,
|
||||
regs.rflags,
|
||||
smp_get_processor_id().data(),
|
||||
ProcessManager::current_pid(),
|
||||
msg1, msg2, msg3,
|
||||
|
@ -460,9 +460,6 @@ unsafe extern "sysv64" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut Arc
|
||||
// mov fs, [rsi + {off_fs}]
|
||||
// mov gs, [rsi + {off_gs}]
|
||||
|
||||
push rbp
|
||||
push rax
|
||||
|
||||
mov [rdi + {off_rbp}], rbp
|
||||
mov rbp, [rsi + {off_rbp}]
|
||||
|
||||
@ -509,17 +506,9 @@ unsafe extern "sysv64" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut Arc
|
||||
);
|
||||
}
|
||||
|
||||
/// 从`switch_to_inner`返回后,执行这个函数
|
||||
///
|
||||
/// 也就是说,当进程再次被调度时,会从这里开始执行
|
||||
#[inline(never)]
|
||||
unsafe extern "sysv64" fn switch_back() {
|
||||
asm!(concat!(
|
||||
"
|
||||
pop rax
|
||||
pop rbp
|
||||
"
|
||||
))
|
||||
#[naked]
|
||||
unsafe extern "sysv64" fn switch_back() -> ! {
|
||||
asm!("ret", options(noreturn));
|
||||
}
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
|
@ -46,11 +46,12 @@ struct ApStartStackInfo {
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn smp_ap_start() -> ! {
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
|
||||
let vaddr = if let Some(t) = smp_cpu_manager()
|
||||
.cpuhp_state(smp_get_processor_id())
|
||||
.thread()
|
||||
{
|
||||
t.kernel_stack().stack_max_address().data() - 16
|
||||
t.kernel_stack_force_ref().stack_max_address().data() - 16
|
||||
} else {
|
||||
// 没有设置ap核心的栈,那么就进入死循环。
|
||||
loop {
|
||||
@ -214,15 +215,16 @@ impl SMPArch for X86_64SMPArch {
|
||||
}
|
||||
|
||||
fn start_cpu(cpu_id: ProcessorId, _cpu_hpstate: &CpuHpCpuState) -> Result<(), SystemError> {
|
||||
kdebug!("start_cpu: cpu_id: {:#x}\n", cpu_id.data());
|
||||
|
||||
Self::copy_smp_start_code();
|
||||
|
||||
fence(Ordering::SeqCst);
|
||||
ipi_send_smp_init();
|
||||
fence(Ordering::SeqCst);
|
||||
ipi_send_smp_startup(cpu_id)?;
|
||||
|
||||
fence(Ordering::SeqCst);
|
||||
ipi_send_smp_startup(cpu_id)?;
|
||||
|
||||
fence(Ordering::SeqCst);
|
||||
|
||||
return Ok(());
|
||||
|
Reference in New Issue
Block a user