From 3cef11eebf3a50fb291583a723c7ae531d270f66 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 13 Oct 2022 12:05:07 +0200 Subject: [PATCH 01/14] boot: stop interrupts --- src/arch/i686/boot.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/i686/boot.asm b/src/arch/i686/boot.asm index 629609b..30fd99c 100644 --- a/src/arch/i686/boot.asm +++ b/src/arch/i686/boot.asm @@ -10,6 +10,7 @@ section .text global _start:function (_start.end - _start) bits 32 _start: + cli mov esp, stack_top xor ebp, ebp From ec61ad06d757ec84cb5bc1d677715524b0b7429e Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 13 Oct 2022 12:18:23 +0200 Subject: [PATCH 02/14] io: add io_wait --- src/arch/i686/port.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/arch/i686/port.rs b/src/arch/i686/port.rs index 1f6f091..cf987ca 100644 --- a/src/arch/i686/port.rs +++ b/src/arch/i686/port.rs @@ -59,3 +59,9 @@ pub fn outd(port: u16, value: u32) asm!("out dx, eax", in("dx") port, in("eax") value, options(nomem, nostack, preserves_flags)); } } + +#[inline(always)] +pub fn io_wait() +{ + outb(0x80, 0); +} From 658d790aa371bd63de0e03cc7a1b17db6ee0a7f2 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 13 Oct 2022 17:50:21 +0200 Subject: [PATCH 03/14] interrupt: initial --- src/arch/i686/instructions.rs | 14 ++++ src/arch/i686/interrupts/exceptions.rs | 66 +++++++++++++++ src/arch/i686/interrupts/idt.rs | 111 +++++++++++++++++++++++++ src/arch/i686/interrupts/mod.rs | 87 +++++++++++++++++++ src/arch/i686/isr.asm | 95 +++++++++++++++++++++ src/arch/i686/mod.rs | 2 + src/arch/mod.rs | 3 + src/elsos.rs | 68 ++++++++++++--- 8 files changed, 433 insertions(+), 13 deletions(-) create mode 100644 src/arch/i686/instructions.rs create mode 100644 src/arch/i686/interrupts/exceptions.rs create mode 100644 src/arch/i686/interrupts/idt.rs create mode 100644 src/arch/i686/interrupts/mod.rs create mode 100644 src/arch/i686/isr.asm diff --git a/src/arch/i686/instructions.rs b/src/arch/i686/instructions.rs new file mode 100644 index 0000000..43bf791 --- /dev/null +++ b/src/arch/i686/instructions.rs @@ -0,0 +1,14 @@ +use core::arch::asm; +use super::interrupts::idt; + +#[inline(always)] +pub unsafe fn lidt(idtr: &idt::descriptor) +{ + asm!("lidt [{}]", in(reg) idtr, options(nostack)); +} + +#[inline(always)] +pub unsafe fn sti() +{ + asm!("sti"); +} diff --git a/src/arch/i686/interrupts/exceptions.rs b/src/arch/i686/interrupts/exceptions.rs new file mode 100644 index 0000000..8d73e50 --- /dev/null +++ b/src/arch/i686/interrupts/exceptions.rs @@ -0,0 +1,66 @@ +use super::State; + +pub enum ExceptionClass +{ + Trap, Fault, Abort, NA +} + +pub struct Exception +{ + pub message: &'static str, + pub class: ExceptionClass, + pub has_error: bool +} + +pub static EXCEPTIONS: [Exception; 32] = +[ + Exception {message: "Divide Error Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Debug Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "NMI Interrupt", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Breakpoint Exception", class: ExceptionClass::Trap, has_error: false}, + Exception {message: "Overflow Exception", class: ExceptionClass::Trap, has_error: false}, + Exception {message: "Bound Range Exceeded Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Invalid Opcode Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Device Not Available Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Double Fault Exception", class: ExceptionClass::Abort, has_error: true}, + Exception {message: "Coprocessor Segment Overrun", class: ExceptionClass::Abort, has_error: false}, + Exception {message: "Invalid TSS Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Segment Not Present", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Stack Fault Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "General Protection Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Page Fault Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + + Exception {message: "x87 Floating-Point Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Alignment Check Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Machine Check Exception", class: ExceptionClass::Abort, has_error: false}, + Exception {message: "SIMD Floating-Point Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Virtualization Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "Control Protection Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, + Exception {message: "Hypervisor Injection Exception", class: ExceptionClass::Fault, has_error: false}, + Exception {message: "VMM Communication Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Security Exception", class: ExceptionClass::Fault, has_error: true}, + Exception {message: "Reserved", class: ExceptionClass::NA, has_error: false}, +]; + +pub fn handler(state: &State) +{ + state.save(); + let interrupt = state.interrupt; + let exception = &EXCEPTIONS[interrupt as usize]; + let error = state.error; + if exception.has_error + { + panic!("{:02x} - {} - error {:08x}", interrupt, exception.message, error); + } + else + { + panic!("{:02x} - {}", interrupt, exception.message); + } +} diff --git a/src/arch/i686/interrupts/idt.rs b/src/arch/i686/interrupts/idt.rs new file mode 100644 index 0000000..8778658 --- /dev/null +++ b/src/arch/i686/interrupts/idt.rs @@ -0,0 +1,111 @@ +use core::mem::size_of; +use crate::arch::i686; + +#[repr(C, packed)] +pub struct descriptor +{ + limit: u16, + base: u32 +} + +enum GateType +{ + Task = 0b0101, + Interrupt16 = 0b0110, + Trap16 = 0b0111, + Interrupt32 = 0b1110, + Trap32 = 0b1111, +} + +#[derive(Copy, Clone)] +#[repr(C, packed)] +struct gate +{ + isr_low: u16, + segment: u16, + reserved: u8, + flags: u8, + isr_high: u16 +} + +impl gate +{ + fn init(&mut self) + { + self.segment = 0x08; + } + + fn set_isr(&mut self, isr: u32) + { + self.isr_low = (isr & 0xffff) as u16; + self.isr_high = (isr >> 16) as u16; + } + + fn set_present(&mut self) + { + self.set_flag(0b1000_0000); + } + + fn unset_present(&mut self) + { + self.unset_flag(0b1000_0000); + } + + fn set_type(&mut self, gate_type: GateType) + { + // unset the type represented by only 0s + self.unset_flag(GateType::Trap32 as u8); + self.set_flag(gate_type as u8); + } + + #[inline(always)] + fn set_flag(&mut self, flag: u8) + { + self.flags |= flag; + } + + #[inline(always)] + fn unset_flag(&mut self, flag: u8) + { + self.flags &= !flag; + } +} + +static mut DESCRIPTOR: descriptor = descriptor +{ + limit: 0, + base: 0 +}; + +static mut IDT: [gate; 32] = [gate +{ + isr_low: 0, + segment: 0, + reserved: 0, + flags: 0, + isr_high: 0 +}; 32]; + +extern "C" +{ + static mut _isr_table: [u32; 32]; +} + +pub unsafe fn init() +{ + DESCRIPTOR.base = &IDT as *const _ as u32; + DESCRIPTOR.limit = (size_of::() * IDT.len() - 1) as u16; + + for (vector, gate) in IDT.iter_mut().enumerate() + { + gate.init(); + gate.set_isr(_isr_table[vector as usize]); + gate.set_type(GateType::Interrupt32); + gate.set_present(); + } +} + +pub unsafe fn load() +{ + i686::instructions::lidt(&DESCRIPTOR); +} diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs new file mode 100644 index 0000000..bc60225 --- /dev/null +++ b/src/arch/i686/interrupts/mod.rs @@ -0,0 +1,87 @@ +use crate::arch::i686::instructions; + +mod exceptions; +pub mod idt; + +#[inline(always)] +pub unsafe fn init() +{ + idt::init(); + idt::load(); +} + +#[inline(always)] +pub unsafe fn enable() +{ + instructions::sti(); +} + +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct State +{ + pub ds: u32, + // pusha + pub edi: u32, + pub esi: u32, + pub ebp: u32, + pub esp: u32, + pub ebx: u32, + pub edx: u32, + pub ecx: u32, + pub eax: u32, + // push interrupt + pub interrupt: u32, + // pushed automatically + pub error: u32, + // pushed by the CPU + pub eip: u32, + pub cs: u32, + pub eflags: u32, +} + +impl State +{ + fn save(self) + { + unsafe + { + let state = &mut crate::INTERRUPT_STATE; + state.eax = self.eax; + state.ebx = self.ebx; + state.ecx = self.ecx; + state.edx = self.edx; + + state.esi = self.esi; + state.edi = self.edi; + state.esp = self.esp; + state.ebp = self.ebp; + + state.cs = self.cs; + state.ds = self.ds; + + state.interrupt = self.interrupt; + state.error = self.error; + + state.eip = self.eip; + state.eflags = self.eflags; + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn interrupt_handler(state: &State) +{ + match state.interrupt + { + 0x00..=0x1f => + { + exceptions::handler(state); + }, + _ => + { + state.save(); + panic!(); + } + }; +} diff --git a/src/arch/i686/isr.asm b/src/arch/i686/isr.asm new file mode 100644 index 0000000..492a774 --- /dev/null +++ b/src/arch/i686/isr.asm @@ -0,0 +1,95 @@ +;macro to define isr_error +%macro isr_error 1 +isr%+%1: + push %1 + jmp isr_common +%endmacro + +;macro to define isr_no_error +%macro isr_no_error 1 +isr%+%1: + ; push a fake error code to have the same structure model + push 0 + push %1 + jmp isr_common +%endmacro + +;define all isr handlers +isr_no_error 0 +isr_no_error 1 +isr_no_error 2 +isr_no_error 3 +isr_no_error 4 +isr_no_error 5 +isr_no_error 6 +isr_no_error 7 +isr_no_error 8 +isr_no_error 9 +isr_error 10 +isr_error 11 +isr_error 12 +isr_error 13 +isr_error 14 +isr_no_error 15 +isr_no_error 16 +isr_error 17 +isr_no_error 18 +isr_no_error 19 +isr_no_error 20 +isr_no_error 21 +isr_no_error 22 +isr_no_error 23 +isr_no_error 24 +isr_no_error 25 +isr_no_error 26 +isr_no_error 27 +isr_no_error 28 +isr_no_error 29 +isr_error 30 +isr_no_error 31 + +isr_common: + cli + ; push eax, ecx, edx, ebx, esi, edi + pushad + cld +; +; ; save ds in eax then push it + xor eax, eax + mov ax, ds + push eax + + ; use kernel_data segment + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + push esp ; pass the saved args to the function via the old stack pointer + extern interrupt_handler + call interrupt_handler + add esp, 4 + + pop eax + + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + popad + + ; remove error code and interrupt number + add esp, 8 + + iret + +; define an isr_table to get easily pointers from rust code +global _isr_table +_isr_table: +%assign i 0 +%rep 32 + dd isr%+i +%assign i i+1 +%endrep diff --git a/src/arch/i686/mod.rs b/src/arch/i686/mod.rs index 429c8f3..b8b4a0c 100644 --- a/src/arch/i686/mod.rs +++ b/src/arch/i686/mod.rs @@ -1,4 +1,6 @@ pub mod gdt; +pub mod instructions; +pub mod interrupts; pub mod port; pub fn init() diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 3860f24..a3096ba 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -3,5 +3,8 @@ pub mod initial; #[cfg(target_arch = "x86")] mod i686; +#[cfg(target_arch = "x86")] +pub use i686::interrupts; + #[cfg(target_arch = "x86")] pub use i686::port; diff --git a/src/elsos.rs b/src/elsos.rs index d0e7d63..a5f1642 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -56,7 +56,12 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) logln!(); tests(); tty::prompt(); - keyboard::get_scancodes(); + unsafe + { + arch::interrupts::init(); + arch::interrupts::enable(); + } + loop {} } } @@ -93,20 +98,45 @@ pub fn ok_fail(value: bool) -> &'static str } } +static mut INTERRUPT_STATE: arch::interrupts::State = arch::interrupts::State +{ + eax: 0, + ebx: 0, + ecx: 0, + edx: 0, + + esi: 0, + edi: 0, + esp: 0, + ebp: 0, + + cs: 0, + ds: 0, + + interrupt: 0, + error: 0, + + eip: 0, + eflags: 0, +}; + #[panic_handler] fn panic(info: &PanicInfo) -> ! { vga::panic(); logln!("\n\x1B[31;49m{}\x1B[39;49m\n", info); - print_memory_state(false); + print_panic_state(false); logln!(""); loop {} } -fn print_memory_state(serial_only: bool) +fn print_panic_state(serial_only: bool) { + let eip: u32; + let eflags: u32; + let eax: u32; let ebx: u32; let ecx: u32; @@ -117,26 +147,38 @@ fn print_memory_state(serial_only: bool) let esp: u32; let ebp: u32; + let cs: u32; + let ds: u32; + unsafe { - eax = crate::get_reg!("eax"); - ebx = crate::get_reg!("ebx"); - ecx = crate::get_reg!("ecx"); - edx = crate::get_reg!("edx"); - - esi = crate::get_reg!("esi"); - edi = crate::get_reg!("edi"); - esp = crate::get_reg!("esp"); - ebp = crate::get_reg!("ebp"); + eip = INTERRUPT_STATE.eip; + eflags = INTERRUPT_STATE.eflags; + eax = INTERRUPT_STATE.eax; + ebx = INTERRUPT_STATE.ebx; + ecx = INTERRUPT_STATE.ecx; + edx = INTERRUPT_STATE.edx; + + esi = INTERRUPT_STATE.esi; + edi = INTERRUPT_STATE.edi; + esp = INTERRUPT_STATE.esp; + ebp = INTERRUPT_STATE.ebp; + + cs = INTERRUPT_STATE.cs; + ds = INTERRUPT_STATE.ds; } if !serial_only { + crate::vga_println!("eip: {:08x} eflags: {:08x}", eip, eflags); crate::vga_println!("eax: {:08x} ebx: {:08x} ecx: {:08x} edx: {:08x}", eax, ebx, ecx, edx); crate::vga_println!("esi: {:08x} edi: {:08x} esp: {:08x} ebp: {:08x}", esi, edi, esp, ebp); + crate::vga_println!(" cs: {:04x} ds: {:04x}", cs, ds); } + crate::serial_println!("eip: {:08x} eflags: {:08x}", eip, eflags); crate::serial_println!("eax: {:08x} ebx: {:08x} ecx: {:08x} edx: {:08x}", eax, ebx, ecx, edx); crate::serial_println!("esi: {:08x} edi: {:08x} esp: {:08x} ebp: {:08x}", esi, edi, esp, ebp); + crate::serial_println!(" cs: {:04x} ds: {:04x}", cs, ds); if !serial_only { @@ -162,6 +204,7 @@ fn print_memory_state(serial_only: bool) } } } + log!("\n\nALLES KAPUT !!!"); } #[macro_export] @@ -170,7 +213,6 @@ macro_rules! oops ($($arg:tt)*) => { $crate::logln!("\x1B[33;49moops at '{}', {}:{}:{}\x1B[39;49m\n", format_args!($($arg)*), file!(), line!(), column!()); - $crate::print_memory_state(true); $crate::serial_println!(""); } } From ace06ffa7ee3db94dbf5a0c21086b8c8067fbb75 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Fri, 14 Oct 2022 01:08:05 +0200 Subject: [PATCH 04/14] pic: initial --- src/arch/i686/interrupts/mod.rs | 2 + src/arch/i686/interrupts/pic.rs | 108 ++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/arch/i686/interrupts/pic.rs diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs index bc60225..6ba95a0 100644 --- a/src/arch/i686/interrupts/mod.rs +++ b/src/arch/i686/interrupts/mod.rs @@ -2,12 +2,14 @@ use crate::arch::i686::instructions; mod exceptions; pub mod idt; +mod pic; #[inline(always)] pub unsafe fn init() { idt::init(); idt::load(); + pic::init(); } #[inline(always)] diff --git a/src/arch/i686/interrupts/pic.rs b/src/arch/i686/interrupts/pic.rs new file mode 100644 index 0000000..96dffdc --- /dev/null +++ b/src/arch/i686/interrupts/pic.rs @@ -0,0 +1,108 @@ +use crate::arch::port::{inb, outb, io_wait}; + +const ICW1_ICW4: u8 = 0x01; /* ICW4 (not) needed */ +const ICW1_SINGLE: u8 = 0x02; /* Single (cascade) mode */ +const ICW1_INTERVAL4: u8 = 0x04; /* Call address interval 4 (8) */ +const ICW1_LEVEL: u8 = 0x08; /* Level triggered (edge) mode */ +const ICW1_INIT: u8 = 0x10; /* Initialization - required! */ + +const ICW4_8086: u8 = 0x01; /* 8086/88 (MCS-80/85) mode */ +const ICW4_AUTO: u8 = 0x02; /* Auto (normal) EOI */ +const ICW4_BUF_SLAVE: u8 = 0x08; /* Buffered mode/slave */ +const ICW4_BUF_MASTER: u8 = 0x0C; /* Buffered mode/master */ +const ICW4_SFNM: u8 = 0x10; /* Special fully nested (not) */ + +const PIC_EOI: u8 = 0x20; /* End-of-interrupt command code */ + +struct PIC +{ + id: u8, + base: u32, + command: u16, + data: u16, + mask: u8 +} + +impl PIC +{ + fn save_mask(&mut self) + { + self.mask = inb(self.data); + } + + fn restore_mask(&self) + { + outb(self.data, self.mask); + } + + fn init_with_offset(&self, offset: u8) + { + // ICW1 + outb(self.command, ICW1_INIT | ICW1_ICW4); + io_wait(); + + // ICW2 + outb(self.data, offset); + io_wait(); + + // ICW3 + if self.id == 1 + { + outb(self.data, 0b0000_0100); + } + else if self.id == 2 + { + outb(self.data, 0b0000_0010); + } + io_wait(); + + // ICW4 + outb(self.data, ICW4_8086); + io_wait(); + } + + fn remap(&mut self, offset: u8) + { + self.save_mask(); + self.init_with_offset(offset); + self.restore_mask(); + } + + fn send_eoi(&self) + { + outb(self.command, PIC_EOI); + } +} + +static PIC1: PIC = PIC +{ + id: 1, + base: 0x20, + command: 0x20, + data: 0x21, + mask: 0 +}; + +static PIC2: PIC = PIC +{ + id: 2, + base: 0xa0, + command: 0xa0, + data: 0xa1, + mask: 0 +}; + +pub unsafe fn init() +{ + PIC1.init_with_offset(0x20); + PIC2.init_with_offset(0x28); +} + +pub unsafe fn send_eoi(irq: u8) +{ + if irq >= 8 + { + PIC2.send_eoi(); + } + PIC1.send_eoi(); +} From ec1d771f057211b0ab28f568ebfd6bc34133b25d Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Fri, 14 Oct 2022 01:48:59 +0200 Subject: [PATCH 05/14] irq: initial support timer interrupt --- src/arch/i686/interrupts/idt.rs | 6 +++--- src/arch/i686/interrupts/irq.rs | 26 ++++++++++++++++++++++++++ src/arch/i686/interrupts/mod.rs | 5 +++++ src/arch/i686/isr.asm | 4 +++- src/elsos.rs | 1 + src/time.rs | 1 + 6 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/arch/i686/interrupts/irq.rs create mode 100644 src/time.rs diff --git a/src/arch/i686/interrupts/idt.rs b/src/arch/i686/interrupts/idt.rs index 8778658..c3082c6 100644 --- a/src/arch/i686/interrupts/idt.rs +++ b/src/arch/i686/interrupts/idt.rs @@ -77,18 +77,18 @@ static mut DESCRIPTOR: descriptor = descriptor base: 0 }; -static mut IDT: [gate; 32] = [gate +static mut IDT: [gate; 33] = [gate { isr_low: 0, segment: 0, reserved: 0, flags: 0, isr_high: 0 -}; 32]; +}; 33]; extern "C" { - static mut _isr_table: [u32; 32]; + static mut _isr_table: [u32; 33]; } pub unsafe fn init() diff --git a/src/arch/i686/interrupts/irq.rs b/src/arch/i686/interrupts/irq.rs new file mode 100644 index 0000000..6b2cf87 --- /dev/null +++ b/src/arch/i686/interrupts/irq.rs @@ -0,0 +1,26 @@ +use super::State; +use super::pic; + +const PIT_INTERRUPT: u8 = 0x00; + +pub struct IRQ +{ + pub message: &'static str, + pub handler: unsafe fn(&State) +} + +pub static IRQS: [IRQ; 1] = +[ + IRQ {message: "Programmable Interrupt Timer Interrupt", handler: pit_interrupt} +]; + +pub unsafe fn handler(state: &State) +{ + (IRQS[(state.interrupt- 0x20) as usize].handler)(state); + pic::send_eoi((state.interrupt - 0x20) as u8); +} + +unsafe fn pit_interrupt(_state: &State) +{ + crate::time::JIFFIES += 1; +} diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs index 6ba95a0..f4c976f 100644 --- a/src/arch/i686/interrupts/mod.rs +++ b/src/arch/i686/interrupts/mod.rs @@ -2,6 +2,7 @@ use crate::arch::i686::instructions; mod exceptions; pub mod idt; +mod irq; mod pic; #[inline(always)] @@ -80,6 +81,10 @@ pub unsafe extern "C" fn interrupt_handler(state: &State) { exceptions::handler(state); }, + 0x20 => + { + irq::handler(state); + } _ => { state.save(); diff --git a/src/arch/i686/isr.asm b/src/arch/i686/isr.asm index 492a774..9623e0d 100644 --- a/src/arch/i686/isr.asm +++ b/src/arch/i686/isr.asm @@ -48,6 +48,8 @@ isr_no_error 29 isr_error 30 isr_no_error 31 +isr_no_error 32 + isr_common: cli ; push eax, ecx, edx, ebx, esi, edi @@ -89,7 +91,7 @@ isr_common: global _isr_table _isr_table: %assign i 0 -%rep 32 +%rep 33 dd isr%+i %assign i i+1 %endrep diff --git a/src/elsos.rs b/src/elsos.rs index a5f1642..256a57c 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -17,6 +17,7 @@ mod multiboot; mod serial; mod memory; mod libc; +mod time; static VERSION: &str = env!("VERSION"); static PATCHLEVEL: &str = env!("PATCHLEVEL"); diff --git a/src/time.rs b/src/time.rs new file mode 100644 index 0000000..6e4d986 --- /dev/null +++ b/src/time.rs @@ -0,0 +1 @@ +pub static mut JIFFIES: u128 = 0; From 71ddd334a1f4fc82feb25edc5fc297e31af28572 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 13 Oct 2022 12:39:31 +0200 Subject: [PATCH 06/14] irq: add keyboard adapt keyboard management to interrupt system --- src/arch/i686/interrupts/idt.rs | 6 ++--- src/arch/i686/interrupts/irq.rs | 10 +++++-- src/arch/i686/interrupts/mod.rs | 2 +- src/arch/i686/isr.asm | 3 ++- src/keyboard/mod.rs | 48 +++++++++++++-------------------- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/arch/i686/interrupts/idt.rs b/src/arch/i686/interrupts/idt.rs index c3082c6..0b4a41b 100644 --- a/src/arch/i686/interrupts/idt.rs +++ b/src/arch/i686/interrupts/idt.rs @@ -77,18 +77,18 @@ static mut DESCRIPTOR: descriptor = descriptor base: 0 }; -static mut IDT: [gate; 33] = [gate +static mut IDT: [gate; 34] = [gate { isr_low: 0, segment: 0, reserved: 0, flags: 0, isr_high: 0 -}; 33]; +}; 34]; extern "C" { - static mut _isr_table: [u32; 33]; + static mut _isr_table: [u32; 34]; } pub unsafe fn init() diff --git a/src/arch/i686/interrupts/irq.rs b/src/arch/i686/interrupts/irq.rs index 6b2cf87..f89c992 100644 --- a/src/arch/i686/interrupts/irq.rs +++ b/src/arch/i686/interrupts/irq.rs @@ -9,9 +9,10 @@ pub struct IRQ pub handler: unsafe fn(&State) } -pub static IRQS: [IRQ; 1] = +pub static IRQS: [IRQ; 2] = [ - IRQ {message: "Programmable Interrupt Timer Interrupt", handler: pit_interrupt} + IRQ {message: "Programmable Interrupt Timer Interrupt", handler: pit_interrupt}, + IRQ {message: "Keyboard Interrupt", handler: keyboard_interrupt} ]; pub unsafe fn handler(state: &State) @@ -24,3 +25,8 @@ unsafe fn pit_interrupt(_state: &State) { crate::time::JIFFIES += 1; } + +unsafe fn keyboard_interrupt(_state: &State) +{ + crate::keyboard::get_scancode(); +} diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs index f4c976f..80aaedf 100644 --- a/src/arch/i686/interrupts/mod.rs +++ b/src/arch/i686/interrupts/mod.rs @@ -81,7 +81,7 @@ pub unsafe extern "C" fn interrupt_handler(state: &State) { exceptions::handler(state); }, - 0x20 => + 0x20..=0x21 => { irq::handler(state); } diff --git a/src/arch/i686/isr.asm b/src/arch/i686/isr.asm index 9623e0d..04ff843 100644 --- a/src/arch/i686/isr.asm +++ b/src/arch/i686/isr.asm @@ -49,6 +49,7 @@ isr_error 30 isr_no_error 31 isr_no_error 32 +isr_no_error 33 isr_common: cli @@ -91,7 +92,7 @@ isr_common: global _isr_table _isr_table: %assign i 0 -%rep 33 +%rep 34 dd isr%+i %assign i i+1 %endrep diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 7e55b1f..06baf86 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -49,37 +49,27 @@ pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option } } -pub fn get_scancodes() +pub fn get_scancode() { - let mut scancode: u8 = 0; - loop - { - let new_scancode = arch::port::inb(KEYBOARD_DATA); + let scancode = arch::port::inb(KEYBOARD_DATA); - if new_scancode == scancode - { - continue; - } - scancode = new_scancode; - - unsafe + unsafe + { + match scancode { - match scancode - { - 0x2A => KEYBOARD_STATE.shift = true, - 0xAA => KEYBOARD_STATE.shift = false, - 0x1D => KEYBOARD_STATE.ctrl = true, - 0x9D => KEYBOARD_STATE.ctrl = false, - _ => { - tty::input(&KeyboardInput { - state: KeyboardState { - shift: KEYBOARD_STATE.shift, - ctrl: KEYBOARD_STATE.ctrl - }, - scancode, - }); - } - }; - } + 0x2A => KEYBOARD_STATE.shift = true, + 0xAA => KEYBOARD_STATE.shift = false, + 0x1D => KEYBOARD_STATE.ctrl = true, + 0x9D => KEYBOARD_STATE.ctrl = false, + _ => { + tty::input(&KeyboardInput { + state: KeyboardState { + shift: KEYBOARD_STATE.shift, + ctrl: KEYBOARD_STATE.ctrl + }, + scancode, + }); + } + }; } } From b9817d21545425c5f2ddbc05b5125c24869c0d62 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Fri, 14 Oct 2022 03:00:24 +0200 Subject: [PATCH 07/14] time: add command to print jiffies --- src/tty/basic_commands.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index da542d7..ee57d61 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -17,6 +17,7 @@ pub fn execute(command: &str) "pb" => printmem_at(0 as *const u8, true), "ps" => print_stack(), "pt" => printtty(), + "jiffies" => jiffies(), "yesss" => yesss(), "panic" => panic(), "" => {}, @@ -196,6 +197,14 @@ fn panic() panic!("panic()"); } +fn jiffies() +{ + unsafe + { + crate::logln!("jiffies = {}", crate::time::JIFFIES); + } +} + fn yesss() { crate::serial_println!("###################%%%%%%%%%####################%%%%%%%%%%%%###((//* "); From 4c35aa02e8bc4d9d3c95e0648220a949c1a77475 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 17 Oct 2022 19:12:19 +0200 Subject: [PATCH 08/14] reboot: use 8042 keyboard controller method --- src/arch/i686/mod.rs | 10 ++++++++++ src/arch/mod.rs | 10 ++++++---- src/tty/basic_commands.rs | 13 +++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/arch/i686/mod.rs b/src/arch/i686/mod.rs index b8b4a0c..c4043b1 100644 --- a/src/arch/i686/mod.rs +++ b/src/arch/i686/mod.rs @@ -1,3 +1,5 @@ +use core::arch::asm; + pub mod gdt; pub mod instructions; pub mod interrupts; @@ -7,3 +9,11 @@ pub fn init() { gdt::init(); } + +pub fn halt() +{ + unsafe + { + asm!("hlt"); + } +} diff --git a/src/arch/mod.rs b/src/arch/mod.rs index a3096ba..06c4467 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -4,7 +4,9 @@ pub mod initial; mod i686; #[cfg(target_arch = "x86")] -pub use i686::interrupts; - -#[cfg(target_arch = "x86")] -pub use i686::port; +pub use i686:: +{ + halt, + interrupts, + port +}; diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index ee57d61..a14f4a2 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -1,5 +1,5 @@ -use core::arch::asm; use core::ffi::c_void; +use crate::arch; use crate::ferramenta; use crate::memory; use crate::vga; @@ -73,15 +73,16 @@ fn halt() ferramenta::shutdown_qemu(); } +// use the 8042 keyboard controller to pulse the reset pin of the CPU fn reboot() { - // jump to the post procedure to reboot - unsafe + let mut good: u8 = 0x02; + while good & 0x02 != 0 { - asm!("push 0FFFFh"); - asm!("push 0000h"); - asm!("retf"); + good = arch::port::inb(0x64); } + arch::port::outb(0x64, 0xFE); + arch::halt(); } fn scheen() From 09e4081084c4e51156207f67da5866f6cb616b3b Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Wed, 26 Oct 2022 14:29:00 +0200 Subject: [PATCH 09/14] interrupts: halt on each loop pass for performance --- src/elsos.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/elsos.rs b/src/elsos.rs index 256a57c..7868654 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -62,7 +62,10 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) arch::interrupts::init(); arch::interrupts::enable(); } - loop {} + loop + { + arch::halt(); + } } } From 112aeb8489a27a306d2f9bd2c4d19a74a96351eb Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sun, 30 Oct 2022 01:16:10 +0200 Subject: [PATCH 10/14] gitignore: ignore gdb history --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d1fb689..745630b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build target grub/grub.cfg +.gdb_history From 68cdfb65ff917dab99f1299b95eed06992772290 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sun, 30 Oct 2022 01:16:46 +0200 Subject: [PATCH 11/14] gdb: add gdbinit for debug --- .gdbinit | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gdbinit diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..4a9f696 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2 @@ +file build/elsos-i686.bin +target remote localhost:1234 From 0a3db6b5860fe4b22a788a2ea40e85417419038f Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sun, 30 Oct 2022 02:39:48 +0200 Subject: [PATCH 12/14] arch: always inline hlt --- src/arch/i686/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/i686/mod.rs b/src/arch/i686/mod.rs index c4043b1..1ff2cf9 100644 --- a/src/arch/i686/mod.rs +++ b/src/arch/i686/mod.rs @@ -10,6 +10,7 @@ pub fn init() gdt::init(); } +#[inline(always)] pub fn halt() { unsafe From a3052f26d6c454660c3e1f68bfedb7b04b66e954 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 31 Oct 2022 17:02:34 +0100 Subject: [PATCH 13/14] interrupts: add unhandled cases --- src/arch/i686/interrupts/idt.rs | 6 +- src/arch/i686/interrupts/irq.rs | 30 ++++- src/arch/i686/interrupts/mod.rs | 8 +- src/arch/i686/isr.asm | 228 +++++++++++++++++++++++++++++++- 4 files changed, 258 insertions(+), 14 deletions(-) diff --git a/src/arch/i686/interrupts/idt.rs b/src/arch/i686/interrupts/idt.rs index 0b4a41b..800b982 100644 --- a/src/arch/i686/interrupts/idt.rs +++ b/src/arch/i686/interrupts/idt.rs @@ -77,18 +77,18 @@ static mut DESCRIPTOR: descriptor = descriptor base: 0 }; -static mut IDT: [gate; 34] = [gate +static mut IDT: [gate; 256] = [gate { isr_low: 0, segment: 0, reserved: 0, flags: 0, isr_high: 0 -}; 34]; +}; 256]; extern "C" { - static mut _isr_table: [u32; 34]; + static mut _isr_table: [u32; 256]; } pub unsafe fn init() diff --git a/src/arch/i686/interrupts/irq.rs b/src/arch/i686/interrupts/irq.rs index f89c992..a782f91 100644 --- a/src/arch/i686/interrupts/irq.rs +++ b/src/arch/i686/interrupts/irq.rs @@ -1,24 +1,36 @@ use super::State; use super::pic; -const PIT_INTERRUPT: u8 = 0x00; - pub struct IRQ { pub message: &'static str, pub handler: unsafe fn(&State) } -pub static IRQS: [IRQ; 2] = +pub static IRQS: [IRQ; 15] = [ IRQ {message: "Programmable Interrupt Timer Interrupt", handler: pit_interrupt}, - IRQ {message: "Keyboard Interrupt", handler: keyboard_interrupt} + IRQ {message: "Keyboard Interrupt", handler: keyboard_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt}, + IRQ {message: "", handler: unhandled_interrupt} ]; pub unsafe fn handler(state: &State) { - (IRQS[(state.interrupt- 0x20) as usize].handler)(state); - pic::send_eoi((state.interrupt - 0x20) as u8); + let irq = state.interrupt - 0x20; + (IRQS[irq as usize].handler)(state); + pic::send_eoi(irq as u8); } unsafe fn pit_interrupt(_state: &State) @@ -30,3 +42,9 @@ unsafe fn keyboard_interrupt(_state: &State) { crate::keyboard::get_scancode(); } + +unsafe fn unhandled_interrupt(state: &State) +{ + let interrupt = state.interrupt; + crate::serial_println!("Got unhandled irq {:02x}", interrupt); +} diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs index 80aaedf..79a7570 100644 --- a/src/arch/i686/interrupts/mod.rs +++ b/src/arch/i686/interrupts/mod.rs @@ -75,20 +75,20 @@ impl State #[no_mangle] pub unsafe extern "C" fn interrupt_handler(state: &State) { - match state.interrupt + let interrupt = state.interrupt; + match interrupt { 0x00..=0x1f => { exceptions::handler(state); }, - 0x20..=0x21 => + 0x20..=0x2f => { irq::handler(state); } _ => { - state.save(); - panic!(); + crate::serial_println!("Got unhandled interrupt {:02x}", interrupt); } }; } diff --git a/src/arch/i686/isr.asm b/src/arch/i686/isr.asm index 04ff843..9891348 100644 --- a/src/arch/i686/isr.asm +++ b/src/arch/i686/isr.asm @@ -15,6 +15,7 @@ isr%+%1: %endmacro ;define all isr handlers +; exceptions isr_no_error 0 isr_no_error 1 isr_no_error 2 @@ -48,8 +49,233 @@ isr_no_error 29 isr_error 30 isr_no_error 31 +; irqs isr_no_error 32 isr_no_error 33 +isr_no_error 34 +isr_no_error 35 +isr_no_error 36 +isr_no_error 37 +isr_no_error 38 +isr_no_error 39 +isr_no_error 40 +isr_no_error 41 +isr_no_error 42 +isr_no_error 43 +isr_no_error 44 +isr_no_error 45 +isr_no_error 46 +isr_no_error 47 + +; other interrupts +isr_no_error 48 +isr_no_error 49 +isr_no_error 50 +isr_no_error 51 +isr_no_error 52 +isr_no_error 53 +isr_no_error 54 +isr_no_error 55 +isr_no_error 56 +isr_no_error 57 +isr_no_error 58 +isr_no_error 59 +isr_no_error 60 +isr_no_error 61 +isr_no_error 62 +isr_no_error 63 +isr_no_error 64 +isr_no_error 65 +isr_no_error 66 +isr_no_error 67 +isr_no_error 68 +isr_no_error 69 +isr_no_error 70 +isr_no_error 71 +isr_no_error 72 +isr_no_error 73 +isr_no_error 74 +isr_no_error 75 +isr_no_error 76 +isr_no_error 77 +isr_no_error 78 +isr_no_error 79 +isr_no_error 80 +isr_no_error 81 +isr_no_error 82 +isr_no_error 83 +isr_no_error 84 +isr_no_error 85 +isr_no_error 86 +isr_no_error 87 +isr_no_error 88 +isr_no_error 89 +isr_no_error 90 +isr_no_error 91 +isr_no_error 92 +isr_no_error 93 +isr_no_error 94 +isr_no_error 95 +isr_no_error 96 +isr_no_error 97 +isr_no_error 98 +isr_no_error 99 +isr_no_error 100 +isr_no_error 101 +isr_no_error 102 +isr_no_error 103 +isr_no_error 104 +isr_no_error 105 +isr_no_error 106 +isr_no_error 107 +isr_no_error 108 +isr_no_error 109 +isr_no_error 110 +isr_no_error 111 +isr_no_error 112 +isr_no_error 113 +isr_no_error 114 +isr_no_error 115 +isr_no_error 116 +isr_no_error 117 +isr_no_error 118 +isr_no_error 119 +isr_no_error 120 +isr_no_error 121 +isr_no_error 122 +isr_no_error 123 +isr_no_error 124 +isr_no_error 125 +isr_no_error 126 +isr_no_error 127 +isr_no_error 128 +isr_no_error 129 +isr_no_error 130 +isr_no_error 131 +isr_no_error 132 +isr_no_error 133 +isr_no_error 134 +isr_no_error 135 +isr_no_error 136 +isr_no_error 137 +isr_no_error 138 +isr_no_error 139 +isr_no_error 140 +isr_no_error 141 +isr_no_error 142 +isr_no_error 143 +isr_no_error 144 +isr_no_error 145 +isr_no_error 146 +isr_no_error 147 +isr_no_error 148 +isr_no_error 149 +isr_no_error 150 +isr_no_error 151 +isr_no_error 152 +isr_no_error 153 +isr_no_error 154 +isr_no_error 155 +isr_no_error 156 +isr_no_error 157 +isr_no_error 158 +isr_no_error 159 +isr_no_error 160 +isr_no_error 161 +isr_no_error 162 +isr_no_error 163 +isr_no_error 164 +isr_no_error 165 +isr_no_error 166 +isr_no_error 167 +isr_no_error 168 +isr_no_error 169 +isr_no_error 170 +isr_no_error 171 +isr_no_error 172 +isr_no_error 173 +isr_no_error 174 +isr_no_error 175 +isr_no_error 176 +isr_no_error 177 +isr_no_error 178 +isr_no_error 179 +isr_no_error 180 +isr_no_error 181 +isr_no_error 182 +isr_no_error 183 +isr_no_error 184 +isr_no_error 185 +isr_no_error 186 +isr_no_error 187 +isr_no_error 188 +isr_no_error 189 +isr_no_error 190 +isr_no_error 191 +isr_no_error 192 +isr_no_error 193 +isr_no_error 194 +isr_no_error 195 +isr_no_error 196 +isr_no_error 197 +isr_no_error 198 +isr_no_error 199 +isr_no_error 200 +isr_no_error 201 +isr_no_error 202 +isr_no_error 203 +isr_no_error 204 +isr_no_error 205 +isr_no_error 206 +isr_no_error 207 +isr_no_error 208 +isr_no_error 209 +isr_no_error 210 +isr_no_error 211 +isr_no_error 212 +isr_no_error 213 +isr_no_error 214 +isr_no_error 215 +isr_no_error 216 +isr_no_error 217 +isr_no_error 218 +isr_no_error 219 +isr_no_error 220 +isr_no_error 221 +isr_no_error 222 +isr_no_error 223 +isr_no_error 224 +isr_no_error 225 +isr_no_error 226 +isr_no_error 227 +isr_no_error 228 +isr_no_error 229 +isr_no_error 230 +isr_no_error 231 +isr_no_error 232 +isr_no_error 233 +isr_no_error 234 +isr_no_error 235 +isr_no_error 236 +isr_no_error 237 +isr_no_error 238 +isr_no_error 239 +isr_no_error 240 +isr_no_error 241 +isr_no_error 242 +isr_no_error 243 +isr_no_error 244 +isr_no_error 245 +isr_no_error 246 +isr_no_error 247 +isr_no_error 248 +isr_no_error 249 +isr_no_error 250 +isr_no_error 251 +isr_no_error 252 +isr_no_error 253 +isr_no_error 254 +isr_no_error 255 isr_common: cli @@ -92,7 +318,7 @@ isr_common: global _isr_table _isr_table: %assign i 0 -%rep 34 +%rep 256 dd isr%+i %assign i i+1 %endrep From 2b60813665e32530119dd47f175d1eb356a08b1f Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 31 Oct 2022 16:48:19 +0100 Subject: [PATCH 14/14] commands: add int testing command --- src/tty/basic_commands.rs | 275 +++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 1 deletion(-) diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index a14f4a2..370a505 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -50,7 +50,15 @@ pub fn execute(command: &str) "vfree" => free(address as *mut c_void, false), _ => {} }; - } + }, + "int" => + { + let n = i32::from_str_radix(arg, 16).unwrap_or_else(|_| { -1 }); + if n >= 0x00 && n <= 0xff + { + int(n as u8); + } + }, _ => crate::println!("{}: unknown or invalid command. Use help for more", command) } } @@ -185,6 +193,271 @@ fn free(address: *mut c_void, kernel_space: bool) } } +// dirty interrupt testing +fn int(n: u8) +{ + use core::arch::asm; + unsafe + { + if n == 0 {asm!("int 0");} + else if n == 1 {asm!("int 1");} + else if n == 2 {asm!("int 2");} + else if n == 3 {asm!("int 3");} + else if n == 4 {asm!("int 4");} + else if n == 5 {asm!("int 5");} + else if n == 6 {asm!("int 6");} + else if n == 7 {asm!("int 7");} + else if n == 8 {asm!("int 8");} + else if n == 9 {asm!("int 9");} + else if n == 10 {asm!("int 10");} + else if n == 11 {asm!("int 11");} + else if n == 12 {asm!("int 12");} + else if n == 13 {asm!("int 13");} + else if n == 14 {asm!("int 14");} + else if n == 15 {asm!("int 15");} + else if n == 16 {asm!("int 16");} + else if n == 17 {asm!("int 17");} + else if n == 18 {asm!("int 18");} + else if n == 19 {asm!("int 19");} + else if n == 20 {asm!("int 20");} + else if n == 21 {asm!("int 21");} + else if n == 22 {asm!("int 22");} + else if n == 23 {asm!("int 23");} + else if n == 24 {asm!("int 24");} + else if n == 25 {asm!("int 25");} + else if n == 26 {asm!("int 26");} + else if n == 27 {asm!("int 27");} + else if n == 28 {asm!("int 28");} + else if n == 29 {asm!("int 29");} + else if n == 30 {asm!("int 30");} + else if n == 31 {asm!("int 31");} + else if n == 32 {asm!("int 32");} + else if n == 33 {asm!("int 33");} + else if n == 34 {asm!("int 34");} + else if n == 35 {asm!("int 35");} + else if n == 36 {asm!("int 36");} + else if n == 37 {asm!("int 37");} + else if n == 38 {asm!("int 38");} + else if n == 39 {asm!("int 39");} + else if n == 40 {asm!("int 40");} + else if n == 41 {asm!("int 41");} + else if n == 42 {asm!("int 42");} + else if n == 43 {asm!("int 43");} + else if n == 44 {asm!("int 44");} + else if n == 45 {asm!("int 45");} + else if n == 46 {asm!("int 46");} + else if n == 47 {asm!("int 47");} + else if n == 48 {asm!("int 48");} + else if n == 49 {asm!("int 49");} + else if n == 50 {asm!("int 50");} + else if n == 51 {asm!("int 51");} + else if n == 52 {asm!("int 52");} + else if n == 53 {asm!("int 53");} + else if n == 54 {asm!("int 54");} + else if n == 55 {asm!("int 55");} + else if n == 56 {asm!("int 56");} + else if n == 57 {asm!("int 57");} + else if n == 58 {asm!("int 58");} + else if n == 59 {asm!("int 59");} + else if n == 60 {asm!("int 60");} + else if n == 61 {asm!("int 61");} + else if n == 62 {asm!("int 62");} + else if n == 63 {asm!("int 63");} + else if n == 64 {asm!("int 64");} + else if n == 65 {asm!("int 65");} + else if n == 66 {asm!("int 66");} + else if n == 67 {asm!("int 67");} + else if n == 68 {asm!("int 68");} + else if n == 69 {asm!("int 69");} + else if n == 70 {asm!("int 70");} + else if n == 71 {asm!("int 71");} + else if n == 72 {asm!("int 72");} + else if n == 73 {asm!("int 73");} + else if n == 74 {asm!("int 74");} + else if n == 75 {asm!("int 75");} + else if n == 76 {asm!("int 76");} + else if n == 77 {asm!("int 77");} + else if n == 78 {asm!("int 78");} + else if n == 79 {asm!("int 79");} + else if n == 80 {asm!("int 80");} + else if n == 81 {asm!("int 81");} + else if n == 82 {asm!("int 82");} + else if n == 83 {asm!("int 83");} + else if n == 84 {asm!("int 84");} + else if n == 85 {asm!("int 85");} + else if n == 86 {asm!("int 86");} + else if n == 87 {asm!("int 87");} + else if n == 88 {asm!("int 88");} + else if n == 89 {asm!("int 89");} + else if n == 90 {asm!("int 90");} + else if n == 91 {asm!("int 91");} + else if n == 92 {asm!("int 92");} + else if n == 93 {asm!("int 93");} + else if n == 94 {asm!("int 94");} + else if n == 95 {asm!("int 95");} + else if n == 96 {asm!("int 96");} + else if n == 97 {asm!("int 97");} + else if n == 98 {asm!("int 98");} + else if n == 99 {asm!("int 99");} + else if n == 100 {asm!("int 100");} + else if n == 101 {asm!("int 101");} + else if n == 102 {asm!("int 102");} + else if n == 103 {asm!("int 103");} + else if n == 104 {asm!("int 104");} + else if n == 105 {asm!("int 105");} + else if n == 106 {asm!("int 106");} + else if n == 107 {asm!("int 107");} + else if n == 108 {asm!("int 108");} + else if n == 109 {asm!("int 109");} + else if n == 110 {asm!("int 110");} + else if n == 111 {asm!("int 111");} + else if n == 112 {asm!("int 112");} + else if n == 113 {asm!("int 113");} + else if n == 114 {asm!("int 114");} + else if n == 115 {asm!("int 115");} + else if n == 116 {asm!("int 116");} + else if n == 117 {asm!("int 117");} + else if n == 118 {asm!("int 118");} + else if n == 119 {asm!("int 119");} + else if n == 120 {asm!("int 120");} + else if n == 121 {asm!("int 121");} + else if n == 122 {asm!("int 122");} + else if n == 123 {asm!("int 123");} + else if n == 124 {asm!("int 124");} + else if n == 125 {asm!("int 125");} + else if n == 126 {asm!("int 126");} + else if n == 127 {asm!("int 127");} + else if n == 128 {asm!("int 128");} + else if n == 129 {asm!("int 129");} + else if n == 130 {asm!("int 130");} + else if n == 131 {asm!("int 131");} + else if n == 132 {asm!("int 132");} + else if n == 133 {asm!("int 133");} + else if n == 134 {asm!("int 134");} + else if n == 135 {asm!("int 135");} + else if n == 136 {asm!("int 136");} + else if n == 137 {asm!("int 137");} + else if n == 138 {asm!("int 138");} + else if n == 139 {asm!("int 139");} + else if n == 140 {asm!("int 140");} + else if n == 141 {asm!("int 141");} + else if n == 142 {asm!("int 142");} + else if n == 143 {asm!("int 143");} + else if n == 144 {asm!("int 144");} + else if n == 145 {asm!("int 145");} + else if n == 146 {asm!("int 146");} + else if n == 147 {asm!("int 147");} + else if n == 148 {asm!("int 148");} + else if n == 149 {asm!("int 149");} + else if n == 150 {asm!("int 150");} + else if n == 151 {asm!("int 151");} + else if n == 152 {asm!("int 152");} + else if n == 153 {asm!("int 153");} + else if n == 154 {asm!("int 154");} + else if n == 155 {asm!("int 155");} + else if n == 156 {asm!("int 156");} + else if n == 157 {asm!("int 157");} + else if n == 158 {asm!("int 158");} + else if n == 159 {asm!("int 159");} + else if n == 160 {asm!("int 160");} + else if n == 161 {asm!("int 161");} + else if n == 162 {asm!("int 162");} + else if n == 163 {asm!("int 163");} + else if n == 164 {asm!("int 164");} + else if n == 165 {asm!("int 165");} + else if n == 166 {asm!("int 166");} + else if n == 167 {asm!("int 167");} + else if n == 168 {asm!("int 168");} + else if n == 169 {asm!("int 169");} + else if n == 170 {asm!("int 170");} + else if n == 171 {asm!("int 171");} + else if n == 172 {asm!("int 172");} + else if n == 173 {asm!("int 173");} + else if n == 174 {asm!("int 174");} + else if n == 175 {asm!("int 175");} + else if n == 176 {asm!("int 176");} + else if n == 177 {asm!("int 177");} + else if n == 178 {asm!("int 178");} + else if n == 179 {asm!("int 179");} + else if n == 180 {asm!("int 180");} + else if n == 181 {asm!("int 181");} + else if n == 182 {asm!("int 182");} + else if n == 183 {asm!("int 183");} + else if n == 184 {asm!("int 184");} + else if n == 185 {asm!("int 185");} + else if n == 186 {asm!("int 186");} + else if n == 187 {asm!("int 187");} + else if n == 188 {asm!("int 188");} + else if n == 189 {asm!("int 189");} + else if n == 190 {asm!("int 190");} + else if n == 191 {asm!("int 191");} + else if n == 192 {asm!("int 192");} + else if n == 193 {asm!("int 193");} + else if n == 194 {asm!("int 194");} + else if n == 195 {asm!("int 195");} + else if n == 196 {asm!("int 196");} + else if n == 197 {asm!("int 197");} + else if n == 198 {asm!("int 198");} + else if n == 199 {asm!("int 199");} + else if n == 200 {asm!("int 200");} + else if n == 201 {asm!("int 201");} + else if n == 202 {asm!("int 202");} + else if n == 203 {asm!("int 203");} + else if n == 204 {asm!("int 204");} + else if n == 205 {asm!("int 205");} + else if n == 206 {asm!("int 206");} + else if n == 207 {asm!("int 207");} + else if n == 208 {asm!("int 208");} + else if n == 209 {asm!("int 209");} + else if n == 210 {asm!("int 210");} + else if n == 211 {asm!("int 211");} + else if n == 212 {asm!("int 212");} + else if n == 213 {asm!("int 213");} + else if n == 214 {asm!("int 214");} + else if n == 215 {asm!("int 215");} + else if n == 216 {asm!("int 216");} + else if n == 217 {asm!("int 217");} + else if n == 218 {asm!("int 218");} + else if n == 219 {asm!("int 219");} + else if n == 220 {asm!("int 220");} + else if n == 221 {asm!("int 221");} + else if n == 222 {asm!("int 222");} + else if n == 223 {asm!("int 223");} + else if n == 224 {asm!("int 224");} + else if n == 225 {asm!("int 225");} + else if n == 226 {asm!("int 226");} + else if n == 227 {asm!("int 227");} + else if n == 228 {asm!("int 228");} + else if n == 229 {asm!("int 229");} + else if n == 230 {asm!("int 230");} + else if n == 231 {asm!("int 231");} + else if n == 232 {asm!("int 232");} + else if n == 233 {asm!("int 233");} + else if n == 234 {asm!("int 234");} + else if n == 235 {asm!("int 235");} + else if n == 236 {asm!("int 236");} + else if n == 237 {asm!("int 237");} + else if n == 238 {asm!("int 238");} + else if n == 239 {asm!("int 239");} + else if n == 240 {asm!("int 240");} + else if n == 241 {asm!("int 241");} + else if n == 242 {asm!("int 242");} + else if n == 243 {asm!("int 243");} + else if n == 244 {asm!("int 244");} + else if n == 245 {asm!("int 245");} + else if n == 246 {asm!("int 246");} + else if n == 247 {asm!("int 247");} + else if n == 248 {asm!("int 248");} + else if n == 249 {asm!("int 249");} + else if n == 250 {asm!("int 250");} + else if n == 251 {asm!("int 251");} + else if n == 252 {asm!("int 252");} + else if n == 253 {asm!("int 253");} + else if n == 254 {asm!("int 254");} + else if n == 255 {asm!("int 255");} + } +} + fn print_stack() { unsafe