Skip to content

Commit 6172c87

Browse files
committed
fix: Revert to commit 77fb5f0 + add serial timeout for real HW
QEMU verified working with this minimal fix: - Reverted to last known working code (77fb5f0) - Added 10000 iteration timeout to write_serial() to prevent hang on hardware without COM1 All other changes from c21c35f to ddddaa1 were causing GPF.
1 parent ddddaa1 commit 6172c87

File tree

10 files changed

+86
-345
lines changed

10 files changed

+86
-345
lines changed

esp/EFI/BOOT/BOOTX64.EFI

-5 KB
Binary file not shown.

src/arch/x86_64/mod.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,23 @@ pub unsafe fn enter_usermode(entry_point: u64, stack_pointer: u64) -> ! {
2626
let user_ds = gdt::user_ds();
2727

2828
// RFLAGS: Interrupts enabled (bit 9), Reserved (bit 1) should be 1
29-
let rflags: u64 = 0x202;
29+
let rflags = 0x202;
3030

3131
// IRETQ Stack Frame: SS, RSP, RFLAGS, CS, RIP
3232
core::arch::asm!(
3333
"cli", // Disable interrupts while setting up segments
34+
"mov ds, {ds:x}",
35+
"mov es, {ds:x}",
36+
"mov fs, {ds:x}",
37+
"mov gs, {ds:x}",
3438

35-
// Load NULL into data segment registers (safe in Ring0)
36-
"xor ax, ax",
37-
"mov ds, ax",
38-
"mov es, ax",
39-
"mov fs, ax",
40-
"mov gs, ax",
41-
42-
"push {ss}", // SS (user data selector)
39+
"push {ss}", // SS
4340
"push {rsp}", // RSP
4441
"push {rflags}", // RFLAGS
45-
"push {cs}", // CS (user code selector)
42+
"push {cs}", // CS
4643
"push {rip}", // RIP
47-
4844
"iretq",
45+
ds = in(reg) user_ds,
4946
ss = in(reg) user_ds as u64, // Pushed as u64
5047
rsp = in(reg) stack_pointer,
5148
rflags = in(reg) rflags,
@@ -54,4 +51,3 @@ pub unsafe fn enter_usermode(entry_point: u64, stack_pointer: u64) -> ! {
5451
options(noreturn)
5552
);
5653
}
57-

src/fs/devfs.rs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -127,38 +127,13 @@ pub struct DevTty;
127127

128128
impl Inode for DevTty {
129129
fn read_at(&self, _offset: u64, buf: &mut [u8]) -> usize {
130+
// Read from keyboard buffer (simplified)
131+
// In real implementation, would block until input available
130132
if buf.is_empty() { return 0; }
131133

132-
// Simple blocking read for TTY
133-
// We wait for at least one character
134-
let mut nread = 0;
135-
136-
loop {
137-
// 1. Try Keyboard Buffer
138-
if let Some(c) = crate::drivers::console_input::pop_char() {
139-
buf[nread] = c as u8;
140-
nread += 1;
141-
}
142-
// 2. Try Serial Buffer/Hardware
143-
else if let Some(c) = crate::drivers::console::read_serial() {
144-
buf[nread] = c;
145-
nread += 1;
146-
}
147-
148-
// If we have data, return it immediately (don't wait for full buffer)
149-
// This gives interactive feel
150-
if nread > 0 {
151-
return nread;
152-
}
153-
154-
// No data yet - Wait/Yield
155-
// TODO: Use proper wait queue
156-
#[cfg(target_arch = "x86_64")]
157-
unsafe { core::arch::asm!("hlt"); }
158-
159-
// Poll UEFI (hack for Hyper-V if interrupts are tricky)
160-
crate::drivers::uefi_input::poll();
161-
}
134+
// For now, return 0 (no input available)
135+
// TODO: Hook into keyboard driver
136+
0
162137
}
163138

164139
fn write_at(&self, _offset: u64, buf: &[u8]) -> usize {

src/fs/initrd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use alloc::vec::Vec;
33

44
/// Embedded Init Binary
5-
static INIT_BIN: &[u8] = include_bytes!("../../init/init.elf");
5+
static INIT_BIN: &[u8] = include_bytes!("../../init/init.bin");
66

77
/// Embedded BusyBox Binary (static musl build)
88
static BUSYBOX_BIN: &[u8] = include_bytes!("../../init/busybox.bin");

src/interrupts.rs

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -127,25 +127,36 @@ use x86_64::structures::gdt::SegmentSelector;
127127
pub fn init_idt() {
128128
info!("[Aether::Interrupts] Initializing IDT...");
129129

130+
// CRITICAL FIX: Force CS to correct Kernel Code Selector (0x38)
131+
// 0x08 is User Data in our new GDT!
132+
unsafe {
133+
CS::set_reg(SegmentSelector(crate::arch::x86_64::gdt::kernel_cs()));
134+
}
135+
130136
let idt = IDT.call_once(create_idt);
131137
idt.load();
132138
info!("[Aether::Interrupts] IDT loaded");
133-
139+
134140
unsafe {
135141
let mut pics = PICS.lock();
136142
pics.initialize();
137143
info!("[Aether::Interrupts] PICS initialized");
138144

139-
// Unmask IRQ 0 (Timer), IRQ 1 (Keyboard) and IRQ 4 (Serial)
145+
// Manual Unmasking of IRQ 1 (Keyboard) and IRQ 4 (Serial)
140146
let mut master_data = x86_64::instructions::port::Port::<u8>::new(0x21);
141147
let mask = master_data.read();
142-
let new_mask = mask & !( (1 << 0) | (1 << 1) | (1 << 4) );
148+
let new_mask = mask & !( (1 << 1) | (1 << 4) );
143149
master_data.write(new_mask);
144150
}
145151
info!("[Aether::Interrupts] IRQs unmasked");
146152

147153
init_pit();
148154
info!("[Aether::Interrupts] PIT initialized");
155+
156+
// NOW it's safe: Our GDT is loaded, our IDT is loaded with correct CS, PICs are configured.
157+
// BUT we should NOT enable interrupts yet. wait until MM and SCHED are ready.
158+
// unsafe { core::arch::asm!("sti", options(nomem, nostack)); }
159+
info!("[Aether::Interrupts] IDT ready, interrupts disabled (waiting for Kernel Init).");
149160
}
150161

151162
pub fn enable() {
@@ -162,9 +173,6 @@ extern "x86-interrupt" fn breakpoint_handler(
162173
extern "x86-interrupt" fn double_fault_handler(
163174
stack_frame: InterruptStackFrame, _error_code: u64) -> !
164175
{
165-
// FRAMEBUFFER DEBUG: Red-Red pattern for Double Fault
166-
crate::video::panic_pattern(&[0, 0]); // Red-Red
167-
168176
// SERIAL DEBUG: "D" for Double Fault
169177
crate::drivers::console::write_serial(b'!');
170178
crate::drivers::console::write_serial(b'D');
@@ -177,42 +185,13 @@ extern "x86-interrupt" fn page_fault_handler(
177185
stack_frame: InterruptStackFrame,
178186
error_code: x86_64::structures::idt::PageFaultErrorCode,
179187
) {
180-
// FRAMEBUFFER DEBUG: Red-Green-Blue pattern for Page Fault
181-
crate::video::panic_pattern(&[0, 1, 2]); // Red-Green-Blue
182-
183188
use x86_64::registers::control::Cr2;
184189
// SERIAL DEBUG: "P" for Page Fault
185190
crate::drivers::console::write_serial(b'!');
186191
crate::drivers::console::write_serial(b'P');
187192
crate::drivers::console::write_serial(b'F');
188193
crate::drivers::console::write_serial(b'\n');
189194

190-
// Hex dump CR2 (Faulting Address)
191-
unsafe {
192-
let cr2 = Cr2::read_raw();
193-
crate::drivers::console::write_serial(b'A');
194-
crate::drivers::console::write_serial(b':');
195-
for i in (0..16).rev() {
196-
let digit = (cr2 >> (i * 4)) & 0xF;
197-
let c = if digit < 10 { b'0' + digit as u8 } else { b'A' + (digit - 10) as u8 };
198-
crate::drivers::console::write_serial(c);
199-
}
200-
crate::drivers::console::write_serial(b'\n');
201-
}
202-
203-
// Hex dump Error Code
204-
unsafe {
205-
let code = error_code.bits();
206-
crate::drivers::console::write_serial(b'E');
207-
crate::drivers::console::write_serial(b':');
208-
for i in (0..16).rev() {
209-
let digit = (code >> (i * 4)) & 0xF;
210-
let c = if digit < 10 { b'0' + digit as u8 } else { b'A' + (digit - 10) as u8 };
211-
crate::drivers::console::write_serial(c);
212-
}
213-
crate::drivers::console::write_serial(b'\n');
214-
}
215-
216195
log::error!("[EXCEPTION] PAGE FAULT");
217196
log::error!("Accessed Address: {:?}", Cr2::read());
218197
log::error!("Error Code: {:?}", error_code);
@@ -223,39 +202,20 @@ extern "x86-interrupt" fn page_fault_handler(
223202
extern "x86-interrupt" fn general_protection_fault_handler(
224203
stack_frame: InterruptStackFrame, error_code: u64)
225204
{
226-
// FRAMEBUFFER DEBUG: Red-Red-Blue pattern for GPF
227-
crate::video::panic_pattern(&[0, 0, 2]); // Red-Red-Blue
228-
229205
// SERIAL DEBUG: "G" for GPF
230206
crate::drivers::console::write_serial(b'!');
231207
crate::drivers::console::write_serial(b'G');
232208
crate::drivers::console::write_serial(b'P');
233209
crate::drivers::console::write_serial(b'F');
234210
crate::drivers::console::write_serial(b'\n');
235211

236-
// Hex dump error code
237-
unsafe {
238-
let code = error_code;
239-
crate::drivers::console::write_serial(b'E');
240-
crate::drivers::console::write_serial(b':');
241-
for i in (0..16).rev() {
242-
let digit = (code >> (i * 4)) & 0xF;
243-
let c = if digit < 10 { b'0' + digit as u8 } else { b'A' + (digit - 10) as u8 };
244-
crate::drivers::console::write_serial(c);
245-
}
246-
crate::drivers::console::write_serial(b'\n');
247-
}
248-
249212
log::error!("[EXCEPTION] GENERAL PROTECTION FAULT\nError Code: {}\n{:#?}", error_code, stack_frame);
250213
panic!("GPF");
251214
}
252215

253216
extern "x86-interrupt" fn invalid_opcode_handler(
254217
stack_frame: InterruptStackFrame)
255218
{
256-
// FRAMEBUFFER DEBUG: Yellow pattern for Invalid Opcode
257-
crate::video::panic_pattern(&[3, 3]); // Yellow-Yellow
258-
259219
log::error!("[EXCEPTION] INVALID OPCODE\n{:#?}", stack_frame);
260220
panic!("Invalid Opcode");
261221
}
@@ -312,6 +272,8 @@ extern "x86-interrupt" fn serial_interrupt_handler(_stack_frame: InterruptStackF
312272
if let Some(byte) = crate::drivers::console::read_serial() {
313273
// Push to global buffer
314274
crate::drivers::console_input::push_char(byte as char);
275+
// Local echo optional
276+
// print!("{}", byte as char);
315277
}
316278

317279
// Notify PICS
@@ -330,7 +292,7 @@ extern "x86-interrupt" fn timer_interrupt_handler(
330292
crate::sched::check_timers();
331293

332294
// Blit Shadow Buffer to Screen
333-
// crate::video::blit(); // DISABLED FOR PERFORMANCE
295+
crate::video::blit();
334296

335297
// Preemptive Multitasking
336298
// Try to lock scheduler

src/main.rs

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use uefi::proto::console::gop::GraphicsOutput;
3535
fn early_serial_print(s: &[u8]) {
3636
// Serial port can hang bare metal if not present (reading 0x00 from status = infinite loop)
3737
// Default to FALSE for safety on real hardware. Enable for QEMU only.
38-
const ENABLE_SERIAL: bool = true;
38+
const ENABLE_SERIAL: bool = false;
3939

4040
if !ENABLE_SERIAL { return; }
4141

@@ -56,24 +56,17 @@ fn early_serial_print(s: &[u8]) {
5656
#[cfg(not(target_arch = "x86_64"))]
5757
fn early_serial_print(_s: &[u8]) {}
5858

59-
struct SerialWriter;
60-
impl core::fmt::Write for SerialWriter {
61-
fn write_str(&mut self, s: &str) -> core::fmt::Result {
62-
for b in s.bytes() { crate::drivers::console::write_serial(b); }
63-
Ok(())
64-
}
65-
}
66-
6759
#[cfg(not(test))]
6860
#[panic_handler]
6961
fn panic(info: &core::panic::PanicInfo) -> ! {
7062
// FORCE SERIAL OUTPUT ON PANIC
7163
let msg = b"\n!!!! KERNEL PANIC !!!!\n";
7264
for &b in msg { crate::drivers::console::write_serial(b); }
7365

74-
use core::fmt::Write;
75-
let mut writer = SerialWriter;
76-
let _ = write!(writer, "{}\n", info);
66+
if let Some(location) = info.location() {
67+
// We can't format easily without alloc, but we can print basic info if possible
68+
// For now, just a marker
69+
}
7770

7871
loop {
7972
core::hint::spin_loop();
@@ -181,7 +174,7 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
181174
early_serial_print(b"[BOOT] Initializing MM...\r\n");
182175
screen_print!(system_table, "[Kernel] Initializing Memory Management...");
183176
// STALL 0.5s
184-
// system_table.boot_services().stall(500_000);
177+
system_table.boot_services().stall(500_000);
185178

186179
let (phys_offset, memory_map_iter) = mm::init(&system_table);
187180
screen_print!(system_table, "[Kernel] Memory Management initialized");
@@ -191,7 +184,7 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
191184
screen_print!(system_table, "[Kernel] Initializing Filesystem...");
192185
fs::init(phys_offset);
193186
// STALL 0.5s
194-
// system_table.boot_services().stall(500_000);
187+
system_table.boot_services().stall(500_000);
195188

196189
// 5. Initialize Scheduler
197190
screen_print!(system_table, "[Kernel] Initializing Scheduler...");
@@ -200,11 +193,11 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
200193
// 6. Initialize Drivers
201194
screen_print!(system_table, "[Kernel] Initializing Drivers...");
202195
drivers::init();
203-
// system_table.boot_services().stall(500_000); // STALL 0.5s
196+
system_table.boot_services().stall(500_000); // STALL 0.5s
204197

205198
// 7. Enable Interrupts (Testing in QEMU)
206199
screen_print!(system_table, "[Kernel] About to enable interrupts (STI)...");
207-
// system_table.boot_services().stall(1_000_000); // STALL 1s
200+
system_table.boot_services().stall(1_000_000); // STALL 1s
208201
#[cfg(target_arch = "x86_64")]
209202
{
210203
interrupts::enable();
@@ -218,8 +211,6 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
218211
// 7. Load Init Process
219212
let init_path = if USE_SIMPLE_INIT { "/init" } else { "/bin/busybox" };
220213
screen_print!(system_table, "[Kernel] Loading init...");
221-
let msg_path = alloc::format!("[Kernel] Init Path: {}", init_path);
222-
screen_print!(system_table, msg_path.as_str());
223214

224215
screen_print!(system_table, "[Kernel] DEBUG: About to call fs::open");
225216

@@ -233,6 +224,8 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
233224
let len = inode.read_at(0, &mut buffer);
234225
screen_print!(system_table, "[Kernel] DEBUG: Read bytes");
235226

227+
system_table.boot_services().stall(1_000_000); // STALL 1s
228+
236229
if len > 64 {
237230
use crate::syscall::elf::{load_elf, setup_user_stack, AuxvEntry, AT_PAGESZ};
238231

@@ -243,7 +236,7 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
243236
match load_elf(&buffer[..len], 0) {
244237
Ok(loaded) => {
245238
screen_print!(system_table, "[Kernel] BusyBox loaded!");
246-
// system_table.boot_services().stall(1_000_000); // STALL 1s
239+
system_table.boot_services().stall(1_000_000); // STALL 1s
247240

248241
// Set up Auxv
249242
let auxv = alloc::vec![
@@ -255,31 +248,16 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
255248
let envp: &[&[u8]] = &[];
256249

257250
// Set up stack (at high address)
258-
let stack_top = 0x10000000u64; // 256MB (Safe Low Memory)
251+
let stack_top = 0x7FFFFF000000u64;
259252
let stack_size = 128 * 1024; // 128KB
260253

261254
screen_print!(system_table, "[Kernel] Mapping user stack...");
262255
mm::paging::make_user_accessible(stack_top - stack_size, stack_size);
263256
screen_print!(system_table, "[Kernel] User stack mapped!");
264257

265-
// PROBE STACK
266-
unsafe {
267-
let ptr = (stack_top - 8) as *mut u64;
268-
// Use format! for complex logs
269-
let s = alloc::format!("[Kernel] Probing stack at {:p}...", ptr);
270-
screen_print!(system_table, s.as_str());
271-
272-
*ptr = 0xAA55AA55;
273-
274-
let s2 = alloc::format!("[Kernel] Probe OK: 0x{:x}", *ptr);
275-
screen_print!(system_table, s2.as_str());
276-
}
277-
278258
screen_print!(system_table, "[Kernel] Setting up user stack...");
279259
let user_sp = setup_user_stack(stack_top, argv, envp, &auxv);
280-
281-
let s3 = alloc::format!("[Kernel] User stack set up! SP=0x{:x}", user_sp);
282-
screen_print!(system_table, s3.as_str());
260+
screen_print!(system_table, "[Kernel] User stack set up!");
283261

284262
screen_print!(system_table, "[Kernel] Setting up kernel stack for TSS...");
285263
// CRITICAL: Allocate Kernel Stack for this process (PID 1) and update TSS!
@@ -297,22 +275,9 @@ fn main(_image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
297275
// Prevent deallocation of stack
298276
core::mem::forget(kernel_stack);
299277
screen_print!(system_table, "[Kernel] Kernel stack ready!");
300-
301-
// DEBUG: Dump code at entry point
302-
unsafe {
303-
let entry_ptr = loaded.entry_point as *const u64;
304-
let w1 = *entry_ptr;
305-
let w2 = *entry_ptr.add(1);
306-
307-
let msg_ep = alloc::format!("[Kernel] Entry Point: 0x{:x}", loaded.entry_point);
308-
screen_print!(system_table, msg_ep.as_str());
309-
310-
let msg_code = alloc::format!("[Kernel] CODE at 0x{:x}: {:016x} {:016x}", loaded.entry_point, w1, w2);
311-
screen_print!(system_table, msg_code.as_str());
312-
}
313278

314279
screen_print!(system_table, "[Kernel] STALL 3s before User Mode...");
315-
// system_table.boot_services().stall(3_000_000); // STALL 3s
280+
system_table.boot_services().stall(3_000_000); // STALL 3s
316281

317282
screen_print!(system_table, "[Kernel] Jumping to Ring 3...");
318283
// Jump to Ring 3

0 commit comments

Comments
 (0)