e6976faaa3
Branding fix across all 3 architectures to match the active Red Bear identity. Previously the kernel fork's start messages still claimed 'Redox OS starting' on aarch64, riscv64, and x86_shared, while the canary/debug patches added later correctly used the new branding. This commit completes the user-facing branding pass: after this, every Red Bear OS boot logs 'RedBear OS starting...' instead of 'Redox OS starting...'. Patches applied: - kernel/P2-redbear-os-branding: 2 of 3 architecture files automatically patched via patch(1) fuzz=5 - kernel/src/arch/x86_shared/start.rs: 1 hunk applied via fuzz=2; the remaining 'Redox OS starting' literal updated via direct edit since patch context for that line was already canary-disturbed
270 lines
8.5 KiB
Rust
270 lines
8.5 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,
|
|
};
|
|
|
|
use crate::numa;
|
|
|
|
/// 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 {
|
|
// EARLY CANARY: write 'R' to COM1 before any kernel init.
|
|
// This proves the serial hardware works and the kernel reached Rust entry.
|
|
// If this character appears but "Redox OS starting..." does not,
|
|
// the hang is in args_ptr.read(), serial::init(), or graphical_debug::init().
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{
|
|
core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'R', options(nostack, preserves_flags));
|
|
}
|
|
|
|
let bootstrap = {
|
|
let args = args_ptr.read();
|
|
|
|
// Set up serial debug
|
|
device::serial::init();
|
|
|
|
// Set up graphical debug
|
|
graphical_debug::init(args.env());
|
|
|
|
// SECOND CANARY: write 'S' to COM1 after serial init.
|
|
// If 'R' appears but 'S' does not, the hang is in serial::init() or graphical_debug::init().
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{
|
|
core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'S', options(nostack, preserves_flags));
|
|
}
|
|
|
|
info!("RedBear OS starting...");
|
|
args.print();
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'1', options(nostack, preserves_flags)); }
|
|
|
|
// Set up GDT
|
|
gdt::init_bsp(stack_end);
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'2', options(nostack, preserves_flags)); }
|
|
|
|
// Set up IDT
|
|
idt::init_bsp();
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'3', options(nostack, preserves_flags)); }
|
|
|
|
// Initialize RMM
|
|
#[cfg(target_arch = "x86")]
|
|
let mut bump_allocator =
|
|
crate::startup::memory::init(&args, Some(0x100000), Some(0x40000000));
|
|
#[cfg(target_arch = "x86_64")]
|
|
let mut bump_allocator = crate::startup::memory::init(&args, Some(0x100000), None);
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'4', options(nostack, preserves_flags)); }
|
|
|
|
// Initialize paging
|
|
paging::init();
|
|
|
|
if cfg!(feature = "acpi") {
|
|
crate::acpi::init_before_mem(args.acpi_rsdp());
|
|
}
|
|
|
|
numa::init(&mut bump_allocator);
|
|
info!("NUMA init done, calling init_mm");
|
|
|
|
crate::memory::init_mm(bump_allocator);
|
|
info!("init_mm done");
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::alternative::early_init(true);
|
|
info!("alternatives done");
|
|
|
|
// Set up syscall instruction
|
|
interrupt::syscall::init();
|
|
|
|
// Setup kernel heap
|
|
allocator::init();
|
|
|
|
// Activate memory logging
|
|
crate::log::init();
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'6', options(nostack, preserves_flags)); }
|
|
|
|
// Initialize miscellaneous processor features
|
|
#[cfg(target_arch = "x86_64")]
|
|
crate::arch::misc::init(LogicalCpuId::BSP);
|
|
|
|
// Initialize devices
|
|
device::init();
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
{ core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'7', options(nostack, preserves_flags)); }
|
|
|
|
// Read ACPI tables, starts APs
|
|
if cfg!(feature = "acpi") {
|
|
crate::acpi::init_after_mem(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);
|
|
}
|
|
}
|