Skip to content

Commit

Permalink
[SnowKernel] Update IDT, Add Keyboard supports
Browse files Browse the repository at this point in the history
  • Loading branch information
quickn committed Jul 12, 2018
1 parent 444cae5 commit 7b7854b
Show file tree
Hide file tree
Showing 35 changed files with 1,854 additions and 520 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ clean:
@rm -r build #target

run: $(img)
@qemu-system-x86_64 -m 4096 -serial mon:stdio -net none -vga std -bios ovmf.fd $(img)
@qemu-system-x86_64 -m 1024 -serial mon:stdio -net none -vga std -bios ovmf.fd $(img)

run-debug: $(img)
@qemu-system-x86_64 -s -S -m 1024 -serial mon:stdio -net none -vga std -bios ovmf.fd $(img)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
Technology is free, SnowFlakeOS

## Library used
- utf16_literal (https://github.com/thepowersgang/rust_os/tree/master/Bootloaders/libuefi/utf16_literal)
- uefi (forked, https://github.com/thepowersgang/rust_os/tree/master/Bootloaders/libuefi)
- slab_allocator (https://github.com/redox-os/slab_allocator)
- x86_64 (forked, https://github.com/rust-osdev/x86_64)

## TODO
### Boot2Snow (x86_64, UEFI)
Expand Down
16 changes: 8 additions & 8 deletions boot2snow/src/boot2snow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,11 @@ pub extern fn init() -> Result<(), ()> {
}

let video_info = kernel_proto::VideoInfo {
physbaseptr: vid_addr as *mut Color,
physbaseptr: vid_addr,
xresolution: display.width(),
yresolution: display.height()
yresolution: display.height(),
splashx: display.width() as i32 / 2,
splashy: (display.height() as i32 + splash.height() as i32) / 2
};

let boot_info = kernel_proto::Info {
Expand All @@ -121,7 +123,10 @@ pub extern fn init() -> Result<(), ()> {
};

// - Execute kernel (passing a magic value and general boot information)
unsafe { asm!("mov rsp, $0" : : "r"(STACK_BASE + STACK_SIZE) : "memory" : "intel", "volatile") };
unsafe {
asm!("mov rsp, $0" : : "r"(STACK_BASE + STACK_SIZE) : "memory" : "intel", "volatile");
}

entrypoint(0x71FF0EF1, &boot_info);
}

Expand Down Expand Up @@ -194,11 +199,6 @@ fn load_kernel_file(filename: &str) -> Result<EntryPoint, Status> {
kernel_file.read( unsafe { slice::from_raw_parts_mut( &mut ent as *mut _ as *mut u8, mem::size_of::<elf::PhEnt>() ) } ).expect("PhEnt read");

if ent.p_type == 1 {
println!("- {:#x}+{:#x} loads +{:#x}+{:#x}",
ent.p_paddr, ent.p_memsz,
ent.p_offset, ent.p_filesz
);

unsafe {
KERNEL_BASE = ent.p_vaddr as usize;
KERNEL_SIZE = ent.p_memsz as usize;
Expand Down
5 changes: 3 additions & 2 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ features = ["spin_no_std"]
rlibc = "1.0"
volatile = "0.1.0"
spin = "0.4.5"
x86_64 = "0.1.2"
x86_64 = { git = "https://github.com/SnowFlakeOS/x86_64.git" }
bitflags = "1"
once = "0.3.3"
slab_allocator = { git = "https://github.com/redox-os/slab_allocator.git", rev = "0a53a0b" }
orbclient = { git = "https://github.com/redox-os/orbclient.git", branch = "no_std" }
orbclient = { git = "https://github.com/redox-os/orbclient.git", branch = "no_std" }
raw-cpuid = "3.1.0"
112 changes: 112 additions & 0 deletions kernel/arch/x86_64/apic.rs
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);
}
}
}
45 changes: 45 additions & 0 deletions kernel/arch/x86_64/gdt.rs
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);
}
}
24 changes: 24 additions & 0 deletions kernel/arch/x86_64/idt.rs
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();
}

23 changes: 4 additions & 19 deletions kernel/arch/x86_64/interrupts.rs
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 {}
}
28 changes: 28 additions & 0 deletions kernel/arch/x86_64/irq.rs
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) }
}
Loading

0 comments on commit 7b7854b

Please sign in to comment.