ca67b1da37
- Rebase all Red Bear kernel changes onto upstream master (4d5d36d4).
- Update version to 0.5.12+rb0.3.0 and add Red Bear author attribution.
- Switch redox_syscall direct dependency to local fork path (../syscall).
- Bump rust-toolchain.toml to nightly-2026-05-24.
- Regenerate Cargo.lock for +rb0.3.0 suffixes and path deps.
222 lines
6.0 KiB
Rust
222 lines
6.0 KiB
Rust
//! This function is where the kernel sets up IRQ handlers
|
|
//! It is incredibly unsafe, and should be minimal in nature
|
|
//! It must create the IDT with the correct entries, those entries are
|
|
//! defined in other files inside of the `arch` module
|
|
use core::{arch::naked_asm, cell::SyncUnsafeCell, mem::offset_of};
|
|
|
|
use crate::{
|
|
allocator,
|
|
arch::{device, gdt, idt, interrupt, paging},
|
|
cpu_set::LogicalCpuId,
|
|
devices::graphical_debug,
|
|
startup::KernelArgs,
|
|
};
|
|
|
|
/// Test of zero values in BSS.
|
|
static BSS_TEST_ZERO: SyncUnsafeCell<usize> = SyncUnsafeCell::new(0);
|
|
/// Test of non-zero values in data.
|
|
static DATA_TEST_NONZERO: SyncUnsafeCell<usize> = SyncUnsafeCell::new(usize::MAX);
|
|
|
|
#[repr(C, align(16))]
|
|
struct StackAlign<T>(T);
|
|
|
|
static STACK: SyncUnsafeCell<StackAlign<[u8; 128 * 1024]>> =
|
|
SyncUnsafeCell::new(StackAlign([0; 128 * 1024]));
|
|
|
|
// FIXME use extern "custom"
|
|
#[unsafe(naked)]
|
|
#[unsafe(no_mangle)]
|
|
extern "C" fn kstart() {
|
|
naked_asm!(
|
|
#[cfg(target_arch = "x86")]
|
|
"
|
|
// BSS should already be zero
|
|
cmp dword ptr [{bss_test_zero}], 0
|
|
jne .Lkstart_crash
|
|
cmp dword ptr [{data_test_nonzero}], 0
|
|
je .Lkstart_crash
|
|
|
|
mov eax, [esp + 4]
|
|
lea esp, [{stack}+{stack_size}-16]
|
|
mov [esp + 4], eax
|
|
mov [esp + 8], esp
|
|
|
|
jmp {start}
|
|
|
|
.Lkstart_crash:
|
|
xor eax, eax
|
|
jmp eax
|
|
",
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
"
|
|
// BSS should already be zero
|
|
cmp qword ptr [rip + {bss_test_zero}], 0
|
|
jne .Lkstart_crash
|
|
cmp qword ptr [rip + {data_test_nonzero}], 0
|
|
je .Lkstart_crash
|
|
|
|
// Note: The System V ABI requires the stack to be aligned to 16 bytes
|
|
// before the call instruction. As we jump rather than call it has to
|
|
// be offset by 8 bytes. Additionally reserve a bit more space at the
|
|
// end of the stack to ensure that the start function returns to
|
|
// address 0.
|
|
lea rsp, [rip + {stack}+{stack_size}-24]
|
|
mov rsi, rsp
|
|
|
|
jmp {start}
|
|
|
|
.Lkstart_crash:
|
|
xor rax, rax
|
|
jmp rax
|
|
",
|
|
|
|
bss_test_zero = sym BSS_TEST_ZERO,
|
|
data_test_nonzero = sym DATA_TEST_NONZERO,
|
|
stack = sym STACK,
|
|
stack_size = const size_of_val(&STACK),
|
|
start = sym start,
|
|
);
|
|
}
|
|
|
|
/// The entry to Rust, all things must be initialized
|
|
unsafe extern "C" fn start(args_ptr: *const KernelArgs, stack_end: usize) -> ! {
|
|
unsafe {
|
|
let bootstrap = {
|
|
let args = args_ptr.read();
|
|
|
|
// Set up serial debug
|
|
device::serial::init();
|
|
|
|
// Set up graphical debug
|
|
graphical_debug::init(args.env());
|
|
|
|
info!("Redox OS starting...");
|
|
args.print();
|
|
|
|
// Set up GDT
|
|
gdt::init_bsp(stack_end);
|
|
|
|
// Set up IDT
|
|
idt::init_bsp();
|
|
|
|
// Initialize RMM
|
|
#[cfg(target_arch = "x86")]
|
|
crate::startup::memory::init(&args, Some(0x100000), Some(0x40000000));
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::startup::memory::init(&args, Some(0x100000), None);
|
|
|
|
// Initialize paging
|
|
paging::init();
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::alternative::early_init(true);
|
|
|
|
// Set up syscall instruction
|
|
interrupt::syscall::init();
|
|
|
|
// Setup kernel heap
|
|
allocator::init();
|
|
|
|
// Activate memory logging
|
|
crate::log::init();
|
|
|
|
// Initialize miscellaneous processor features
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::misc::init(LogicalCpuId::BSP);
|
|
|
|
// Initialize devices
|
|
device::init();
|
|
|
|
// Read ACPI tables, starts APs
|
|
if cfg!(feature = "acpi") {
|
|
crate::acpi::init(args.acpi_rsdp());
|
|
device::init_after_acpi();
|
|
}
|
|
crate::profiling::init();
|
|
|
|
// Initialize all of the non-core devices not otherwise needed to complete initialization
|
|
device::init_noncore();
|
|
|
|
args.bootstrap()
|
|
};
|
|
|
|
crate::startup::kmain(bootstrap);
|
|
}
|
|
}
|
|
|
|
pub struct KernelArgsAp {
|
|
pub stack_end: *mut u8,
|
|
pub cpu_id: LogicalCpuId,
|
|
pub pcr_ptr: *mut gdt::ProcessorControlRegion,
|
|
pub idt_ptr: *mut idt::Idt,
|
|
}
|
|
|
|
// FIXME use extern "custom"
|
|
#[unsafe(naked)]
|
|
pub extern "C" fn kstart_ap() {
|
|
naked_asm!(
|
|
#[cfg(target_arch = "x86")]
|
|
"
|
|
mov esp, dword ptr [edi + {args_stack}]
|
|
mov [esp + 4], edi
|
|
mov [esp + 8], esp
|
|
|
|
jmp {start_ap}
|
|
",
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
"
|
|
// Note: The System V ABI requires the stack to be aligned to 16 bytes
|
|
// before the call instruction. As we jump rather than call it has to
|
|
// be offset by 8 bytes. Additionally reserve a bit more space at the
|
|
// end of the stack to ensure that the start function returns to
|
|
// address 0.
|
|
mov rax, qword ptr [rdi + {args_stack}]
|
|
lea rsp, [rax - 24]
|
|
|
|
jmp {start_ap}
|
|
",
|
|
|
|
args_stack = const offset_of!(KernelArgsAp, stack_end),
|
|
start_ap = sym start_ap,
|
|
);
|
|
}
|
|
|
|
/// Entry to rust for an AP
|
|
unsafe extern "C" fn start_ap(args_ptr: *const KernelArgsAp) -> ! {
|
|
unsafe {
|
|
let cpu_id = {
|
|
let args = &*args_ptr;
|
|
|
|
// Set up GDT
|
|
gdt::install_pcr(args.pcr_ptr);
|
|
|
|
// Set up IDT
|
|
idt::install_idt(args.idt_ptr);
|
|
|
|
// Initialize paging
|
|
paging::init();
|
|
|
|
crate::profiling::init();
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::alternative::early_init(false);
|
|
|
|
// Set up syscall instruction
|
|
interrupt::syscall::init();
|
|
|
|
// Initialize miscellaneous processor features
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::misc::init(args.cpu_id);
|
|
|
|
// Initialize devices (for AP)
|
|
device::init_ap();
|
|
|
|
args.cpu_id
|
|
};
|
|
|
|
crate::startup::kmain_ap(cpu_id);
|
|
}
|
|
}
|