summaryrefslogtreecommitdiffstats
path: root/src/interrupts.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/interrupts.rs96
1 files changed, 56 insertions, 40 deletions
diff --git a/src/interrupts.rs b/src/interrupts.rs
index 204d3d7..90d5bbb 100644
--- a/src/interrupts.rs
+++ b/src/interrupts.rs
@@ -12,13 +12,13 @@ use core::sync::atomic::{AtomicU16, Ordering};
12#[derive(Copy, Clone)] 12#[derive(Copy, Clone)]
13#[repr(C, packed)] 13#[repr(C, packed)]
14struct IdtEntry { 14struct IdtEntry {
15 offset_lo: u16, 15 offset_lo: u16,
16 selector: u16, 16 selector: u16,
17 ist: u8, 17 ist: u8,
18 flags: u8, 18 flags: u8,
19 offset_mid: u16, 19 offset_mid: u16,
20 offset_hi: u32, 20 offset_hi: u32,
21 _reserved: u32, 21 _reserved: u32,
22} 22}
23 23
24/// Fill one IDT entry at the given offset (in bytes). 24/// Fill one IDT entry at the given offset (in bytes).
@@ -27,13 +27,13 @@ unsafe fn idt_set_entry(idt: *mut u8, vec: u8, handler: u64, selector: u16, flag
27 let off = (vec as usize) * 16; 27 let off = (vec as usize) * 16;
28 let p = idt.add(off) as *mut IdtEntry; 28 let p = idt.add(off) as *mut IdtEntry;
29 p.write(IdtEntry { 29 p.write(IdtEntry {
30 offset_lo: handler as u16, 30 offset_lo: handler as u16,
31 selector, 31 selector,
32 ist: 0, 32 ist: 0,
33 flags: flags | 0x80, // bit 7 = present 33 flags: flags | 0x80, // bit 7 = present
34 offset_mid: (handler >> 16) as u16, 34 offset_mid: (handler >> 16) as u16,
35 offset_hi: (handler >> 32) as u32, 35 offset_hi: (handler >> 32) as u32,
36 _reserved: 0, 36 _reserved: 0,
37 }); 37 });
38 } 38 }
39} 39}
@@ -46,9 +46,9 @@ static mut IDTR: [u16; 5] = [0; 5]; // 2-byte limit + 4-byte base (48-bit pseudo
46// PIC (8259A) 46// PIC (8259A)
47// --------------------------------------------------------------------------- 47// ---------------------------------------------------------------------------
48 48
49const PIC1_CMD: u16 = 0x20; 49const PIC1_CMD: u16 = 0x20;
50const PIC1_DATA: u16 = 0x21; 50const PIC1_DATA: u16 = 0x21;
51const PIC2_CMD: u16 = 0xA0; 51const PIC2_CMD: u16 = 0xA0;
52const PIC2_DATA: u16 = 0xA1; 52const PIC2_DATA: u16 = 0xA1;
53 53
54const PIC_EOI: u8 = 0x20; 54const PIC_EOI: u8 = 0x20;
@@ -89,8 +89,8 @@ fn eoi(irq: u8) {
89// PIT timer (channel 0, ~100 Hz) 89// PIT timer (channel 0, ~100 Hz)
90// --------------------------------------------------------------------------- 90// ---------------------------------------------------------------------------
91 91
92const PIT_CMD: u16 = 0x43; 92const PIT_CMD: u16 = 0x43;
93const PIT_CH0: u16 = 0x40; 93const PIT_CH0: u16 = 0x40;
94const PIT_FREQ: u64 = 1_193_182; 94const PIT_FREQ: u64 = 1_193_182;
95 95
96/// Set up PIT channel 0 in mode 2 (rate generator) at `hz` (1–1000ish). 96/// Set up PIT channel 0 in mode 2 (rate generator) at `hz` (1–1000ish).
@@ -177,7 +177,9 @@ impl KeyBuf {
177 if next.wrapping_sub(h) as u16 > 255 { 177 if next.wrapping_sub(h) as u16 > 255 {
178 return; // drop — ring is full 178 return; // drop — ring is full
179 } 179 }
180 unsafe { *self.buf[t as usize & 255].get() = byte; } 180 unsafe {
181 *self.buf[t as usize & 255].get() = byte;
182 }
181 // Ensure byte is globally visible before incrementing tail. 183 // Ensure byte is globally visible before incrementing tail.
182 self.tail.store(next, Ordering::Release); 184 self.tail.store(next, Ordering::Release);
183 } 185 }
@@ -206,8 +208,8 @@ core::arch::global_asm!(
206 ".globl isr_stub_32", 208 ".globl isr_stub_32",
207 ".p2align 4", 209 ".p2align 4",
208 "isr_stub_32:", 210 "isr_stub_32:",
209 " push 0", // error code (non-exception) 211 " push 0", // error code (non-exception)
210 " push 32", // vector 212 " push 32", // vector
211 " jmp isr_common", 213 " jmp isr_common",
212 "", 214 "",
213 ".globl isr_stub_33", 215 ".globl isr_stub_33",
@@ -243,7 +245,7 @@ core::arch::global_asm!(
243 " push r14", 245 " push r14",
244 " push r15", 246 " push r15",
245 "", 247 "",
246 " mov rdi, rsp", // first arg: pointer to saved registers 248 " mov rcx, rsp", // first arg (rcx = MS x64 ABI)
247 " call isr_dispatch", 249 " call isr_dispatch",
248 "", 250 "",
249 " pop r15", 251 " pop r15",
@@ -261,36 +263,50 @@ core::arch::global_asm!(
261 " pop rdx", 263 " pop rdx",
262 " pop rcx", 264 " pop rcx",
263 " pop rax", 265 " pop rax",
264 " add rsp, 16", // pop vector + error code 266 " add rsp, 16", // pop vector + error code
265 " iretq", 267 " iretq",
266); 268);
267 269
268/// Saved register frame (as pushed by `isr_common`). 270/// Saved register frame (as pushed by `isr_common`).
269#[repr(C)] 271#[repr(C)]
270struct IntFrame { 272struct IntFrame {
271 r15: u64, r14: u64, r13: u64, r12: u64, 273 r15: u64,
272 r11: u64, r10: u64, r9: u64, r8: u64, 274 r14: u64,
273 rdi: u64, rsi: u64, rbp: u64, rbx: u64, 275 r13: u64,
274 rdx: u64, rcx: u64, rax: u64, 276 r12: u64,
275 vector: u64, 277 r11: u64,
276 error: u64, 278 r10: u64,
277 rip: u64, 279 r9: u64,
278 cs: u64, 280 r8: u64,
279 rflags: u64, 281 rdi: u64,
282 rsi: u64,
283 rbp: u64,
284 rbx: u64,
285 rdx: u64,
286 rcx: u64,
287 rax: u64,
288 vector: u64,
289 error: u64,
290 rip: u64,
291 cs: u64,
292 rflags: u64,
280} 293}
281 294
282/// Called from the asm common handler — dispatches to the right Rust handler. 295/// Called from the asm common handler — dispatches to the right Rust handler.
283#[no_mangle] 296#[no_mangle]
284extern "C" fn isr_dispatch(frame: &IntFrame) { 297unsafe extern "C" fn isr_dispatch(frame: &IntFrame) {
285 match frame.vector { 298 unsafe {
286 32 => timer_irq(), 299 match frame.vector {
287 33 => keyboard_irq(), 300 32 => eoi(0),
288 0xFF => { /* spurious — ignore */ } 301 33 => {
289 other => { 302 let byte: u8;
290 // Log unexpected interrupt on serial (but don't halt — might be benign). 303 core::arch::asm!("in al, dx", out("al") byte, in("dx") 0x60u16,
291 crate::serial::write_str("intr: unhandled vector "); 304 options(nostack, preserves_flags));
292 crate::serial::put_byte(other as u8); 305 // Push scancode to ring buffer (called with interrupts disabled).
293 crate::serial::put_byte(b'\n'); 306 KEYBUF.push(byte);
307 eoi(1);
308 }
309 _ => {}
294 } 310 }
295 } 311 }
296} 312}
@@ -346,7 +362,7 @@ pub fn init() {
346 362
347 // Build the IDTR pseudo-descriptor. 363 // Build the IDTR pseudo-descriptor.
348 IDTR = [ 364 IDTR = [
349 (256u16 * 16 - 1) as u16, // limit = 256*16 - 1 365 (256u16 * 16 - 1) as u16, // limit = 256*16 - 1
350 idt_ptr as u16, // base lo 366 idt_ptr as u16, // base lo
351 (idt_ptr as u64 >> 16) as u16, // base mid 367 (idt_ptr as u64 >> 16) as u16, // base mid
352 (idt_ptr as u64 >> 32) as u16, // base hi 368 (idt_ptr as u64 >> 32) as u16, // base hi