-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SnowKernel] Update IDT, Add Keyboard supports
- Loading branch information
quickn
committed
Jul 12, 2018
1 parent
444cae5
commit 7b7854b
Showing
35 changed files
with
1,854 additions
and
520 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
//! Some code was borrowed from [Redox OS Kernel](https://gitlab.redox-os.org/redox-os/kernel) | ||
use core::intrinsics::{volatile_load, volatile_store}; | ||
use raw_cpuid::CpuId; | ||
use x86_64::registers::model_specific::Msr; | ||
|
||
pub const IA32_APIC_BASE: u32 = 0x1b; | ||
pub const IA32_X2APIC_SIVR: u32 = 0x80f; | ||
pub const IA32_X2APIC_APICID: u32 = 0x802; | ||
pub const IA32_X2APIC_VERSION: u32 = 0x803; | ||
pub const IA32_X2APIC_EOI: u32 = 0x80b; | ||
pub const IA32_X2APIC_ICR: u32 = 0x830; | ||
|
||
pub static mut APIC: Apic = Apic { | ||
address: 0, | ||
x2: false, | ||
}; | ||
|
||
pub unsafe fn init() { | ||
APIC.init(); | ||
} | ||
|
||
pub unsafe fn init_ap() { | ||
APIC.init_ap(); | ||
} | ||
|
||
pub struct Apic { | ||
pub address: usize, | ||
pub x2: bool | ||
} | ||
|
||
impl Apic { | ||
unsafe fn init(&mut self) { | ||
self.address = (Msr::new(IA32_APIC_BASE).read() as usize & 0xFFFF_0000) + ::KERNEL_BASE; | ||
self.x2 = CpuId::new().get_feature_info().unwrap().has_x2apic(); | ||
self.init_ap(); | ||
} | ||
|
||
unsafe fn init_ap(&mut self) { | ||
if self.x2 { | ||
Msr::new(IA32_APIC_BASE).write(Msr::new(IA32_APIC_BASE).read() | 1 << 10); | ||
Msr::new(IA32_X2APIC_SIVR).write(0x100); | ||
} else { | ||
self.write(0xF0, 0x100); | ||
} | ||
} | ||
|
||
unsafe fn read(&self, reg: u32) -> u32 { | ||
volatile_load((self.address + reg as usize) as *const u32) | ||
} | ||
|
||
unsafe fn write(&mut self, reg: u32, value: u32) { | ||
volatile_store((self.address + reg as usize) as *mut u32, value); | ||
} | ||
|
||
pub fn id(&self) -> u32 { | ||
if self.x2 { | ||
unsafe { Msr::new(IA32_X2APIC_APICID).read() as u32 } | ||
} else { | ||
unsafe { self.read(0x20) } | ||
} | ||
} | ||
|
||
pub fn version(&self) -> u32 { | ||
if self.x2 { | ||
unsafe { Msr::new(IA32_X2APIC_VERSION).read() as u32 } | ||
} else { | ||
unsafe { self.read(0x30) } | ||
} | ||
} | ||
|
||
pub fn icr(&self) -> u64 { | ||
if self.x2 { | ||
unsafe { Msr::new(IA32_X2APIC_ICR).read() } | ||
} else { | ||
unsafe { | ||
(self.read(0x310) as u64) << 32 | self.read(0x300) as u64 | ||
} | ||
} | ||
} | ||
|
||
pub fn set_icr(&mut self, value: u64) { | ||
if self.x2 { | ||
unsafe { Msr::new(IA32_X2APIC_ICR).write(value); } | ||
} else { | ||
unsafe { | ||
while self.read(0x300) & 1 << 12 == 1 << 12 {} | ||
self.write(0x310, (value >> 32) as u32); | ||
self.write(0x300, value as u32); | ||
while self.read(0x300) & 1 << 12 == 1 << 12 {} | ||
} | ||
} | ||
} | ||
|
||
pub fn ipi(&mut self, apic_id: usize) { | ||
let mut icr = 0x4040; | ||
if self.x2 { | ||
icr |= (apic_id as u64) << 32; | ||
} else { | ||
icr |= (apic_id as u64) << 56; | ||
} | ||
self.set_icr(icr); | ||
} | ||
|
||
pub unsafe fn eoi(&mut self) { | ||
if self.x2 { | ||
Msr::new(IA32_X2APIC_EOI).write(0); | ||
} else { | ||
self.write(0xB0, 0); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use x86_64::VirtAddr; | ||
use x86_64::structures::tss::TaskStateSegment; | ||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor, SegmentSelector}; | ||
|
||
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0; | ||
|
||
lazy_static! { | ||
static ref TSS: TaskStateSegment = { | ||
let mut tss = TaskStateSegment::new(); | ||
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = { | ||
const STACK_SIZE: usize = 4096; | ||
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; | ||
|
||
let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); | ||
let stack_end = stack_start + STACK_SIZE; | ||
stack_end | ||
}; | ||
tss | ||
}; | ||
} | ||
|
||
lazy_static! { | ||
static ref GDT: (GlobalDescriptorTable, Selectors) = { | ||
let mut gdt = GlobalDescriptorTable::new(); | ||
let code_selector = gdt.add_entry(Descriptor::kernel_code_segment()); | ||
let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS)); | ||
(gdt, Selectors { code_selector, tss_selector }) | ||
}; | ||
} | ||
|
||
struct Selectors { | ||
code_selector: SegmentSelector, | ||
tss_selector: SegmentSelector, | ||
} | ||
|
||
pub fn init() { | ||
use x86_64::instructions::segmentation::set_cs; | ||
use x86_64::instructions::tables::load_tss; | ||
|
||
GDT.0.load(); | ||
unsafe { | ||
set_cs(GDT.1.code_selector); | ||
load_tss(GDT.1.tss_selector); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use x86_64::structures::idt::{Idt, ExceptionStackFrame}; | ||
|
||
use super::interrupts; | ||
use super::irq; | ||
use super::gdt; | ||
|
||
lazy_static! { | ||
static ref IDT: Idt = { | ||
let mut idt = Idt::new(); | ||
|
||
//idt.divide_by_zero.set_handler_fn(divide_by_zero); | ||
idt.breakpoint.set_handler_fn(interrupts::breakpoint_handler); | ||
idt.double_fault.set_handler_fn(interrupts::double_fault_handler); | ||
|
||
//idt.interrupts[33].set_handler_fn(irq::keyboard_handler); // 33 -> Keyboard | ||
|
||
idt | ||
}; | ||
} | ||
|
||
pub fn init() { | ||
IDT.load(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,16 @@ | ||
//! Some code was borrowed from [Phil Opp's Blog](https://os.phil-opp.com) | ||
use x86_64::structures::idt::{Idt, ExceptionStackFrame}; | ||
use x86_64::structures::idt::ExceptionStackFrame; | ||
|
||
lazy_static! { | ||
static ref IDT: Idt = { | ||
let mut idt = Idt::new(); | ||
|
||
idt.breakpoint.set_handler_fn(breakpoint_handler); | ||
idt.double_fault.set_handler_fn(double_fault_handler); | ||
|
||
idt | ||
}; | ||
} | ||
|
||
pub fn init() { | ||
IDT.load(); | ||
} | ||
|
||
extern "x86-interrupt" fn breakpoint_handler( | ||
pub extern "x86-interrupt" fn breakpoint_handler( | ||
stack_frame: &mut ExceptionStackFrame) | ||
{ | ||
println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); | ||
} | ||
|
||
extern "x86-interrupt" fn double_fault_handler( | ||
pub extern "x86-interrupt" fn double_fault_handler( | ||
stack_frame: &mut ExceptionStackFrame, _error_code: u64) | ||
{ | ||
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); | ||
println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); | ||
loop {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use x86_64::structures::idt::ExceptionStackFrame; | ||
|
||
use super::{apic, pic}; | ||
|
||
unsafe fn trigger(irq: u8) { | ||
extern { | ||
fn irq_trigger(irq: u8); | ||
} | ||
|
||
if irq < 16 { | ||
if irq >= 8 { | ||
pic::SLAVE.mask_set(irq - 8); | ||
pic::MASTER.ack(); | ||
pic::SLAVE.ack(); | ||
} else { | ||
pic::MASTER.mask_set(irq); | ||
pic::MASTER.ack(); | ||
} | ||
} | ||
|
||
irq_trigger(irq); | ||
} | ||
|
||
pub extern "x86-interrupt" fn keyboard_handler( | ||
_stack_frame: &mut ExceptionStackFrame) | ||
{ | ||
unsafe { trigger(1) } | ||
} |
Oops, something went wrong.