1use core::fmt::Write;
6use core::ptr;
7use core::{arch::asm, panic::PanicInfo};
8
9use kernel::debug;
10
11use x86_q35::serial::{BlockingSerialPort, COM1_BASE};
12
13use crate::{CHIP, PROCESSES, PROCESS_PRINTER};
14
15fn exit_qemu() -> ! {
20 unsafe {
21 asm!(
22 "
23 mov dx, 0xf4
24 mov al, 0x01
25 out dx,al
26 "
27 );
28 }
29
30 let mut com1 = unsafe { BlockingSerialPort::new(COM1_BASE) };
34 let _ = com1.write_fmt(format_args!(
35 "BUG: QEMU did not exit.\
36 \r\n The isa-debug-exit device is missing or is at a wrong address.\
37 \r\n Please make sure the QEMU command line uses\
38 \r\n the `-device isa-debug-exit,iobase=0xf4,iosize=0x04` argument.\
39 \r\nHINT: Use `killall qemu-system-i386` or the Task Manager to stop.\
40 \r\n"
41 ));
42
43 loop {
46 unsafe { asm!("hlt") }
47 }
48}
49
50#[cfg(not(test))]
52#[panic_handler]
53unsafe fn panic_handler(pi: &PanicInfo) -> ! {
54 let mut com1 = BlockingSerialPort::new(COM1_BASE);
55
56 debug::panic_print(
57 &mut com1,
58 pi,
59 &x86::support::nop,
60 PROCESSES.unwrap().as_slice(),
61 &*ptr::addr_of!(CHIP),
62 &*ptr::addr_of!(PROCESS_PRINTER),
63 );
64
65 exit_qemu();
66}