Files
RedBear-OS/src/arch/x86_shared/start.rs
T
vasilito e6976faaa3 kernel: update 'Redox OS starting' -> 'RedBear OS starting' on all architectures
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
2026-07-12 01:58:02 +03:00

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