cpuid support

This commit is contained in:
Jack Halford 2018-04-05 12:25:53 +02:00
parent 19bf69bb29
commit 0f79f2843c
16 changed files with 339 additions and 89 deletions

View file

@ -4,3 +4,6 @@
[submodule "x86"] [submodule "x86"]
path = x86 path = x86
url = https://github.com/jzck/x86.git url = https://github.com/jzck/x86.git
[submodule "rust-cpuid"]
path = rust-cpuid
url = https://github.com/jzck/rust-cpuid

View file

@ -1,7 +1,7 @@
[package] [package]
name = "bluesnow" name = "bluesnow"
version = "0.1.0" version = "0.1.0"
authors = ["Jack Halford <jack@crans.org>", "William Escande <wescande@student.42.fr>"] authors = ["Jack Halford <j@crans.org>", "William Escande <wescande@student.42.fr>"]
[lib] [lib]
crate-type = ["staticlib"] crate-type = ["staticlib"]
@ -10,9 +10,10 @@ crate-type = ["staticlib"]
rlibc = "1.0" rlibc = "1.0"
bitflags = "1.0.1" bitflags = "1.0.1"
spin = "0.4" spin = "0.4"
multiboot2 = { path = "multiboot2-elf64" }
slab_allocator = "0.3.1" slab_allocator = "0.3.1"
x86 = { path = "x86" } multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag
x86 = { path = "x86" } # forked for IA32
raw-cpuid = { path = "rust-cpuid" } # forked for IA32
[dependencies.lazy_static] [dependencies.lazy_static]
version = "1.0.0" version = "1.0.0"

1
kernel-rs/rust-cpuid Submodule

@ -0,0 +1 @@
Subproject commit 07299b93df57fcee2b6aec61502a5135b99967f8

View file

@ -0,0 +1,133 @@
extern crate raw_cpuid;
use core::fmt::{Result};
use self::raw_cpuid::CpuId;
pub fn cpu_info() -> Result {
let cpuid = CpuId::new();
if let Some(info) = cpuid.get_vendor_info() {
println!("CPU Vendor: {}", info.as_string());
}
if let Some(info) = cpuid.get_extended_function_info() {
if let Some(brand) = info.processor_brand_string() {
println!("CPU Model: {}", brand);
}
}
if let Some(info) = cpuid.get_processor_frequency_info() {
println!("CPU Base MHz: {}", info.processor_base_frequency());
println!("CPU Max MHz: {}", info.processor_max_frequency());
println!("Bus MHz: {}", info.bus_frequency());
} else {
set_color!(Red);
println!("couldn't retrieve CPU frequency info");
set_color!();
}
if let Some(info) = cpuid.get_feature_info() {
print!("Features:");
if info.has_fpu() { print!(" fpu") };
if info.has_vme() { print!(", vme") };
if info.has_de() { print!(", de") };
if info.has_pse() { print!(", pse") };
if info.has_tsc() { print!(", tsc") };
if info.has_msr() { print!(", msr") };
if info.has_pae() { print!(", pae") };
if info.has_mce() { print!(", mce") };
if info.has_cmpxchg8b() { print!(", cx8") };
if info.has_apic() { print!(", apic") };
if info.has_sysenter_sysexit() { print!(", sep") };
if info.has_mtrr() { print!(", mtrr") };
if info.has_pge() { print!(", pge") };
if info.has_mca() { print!(", mca") };
if info.has_cmov() { print!(", cmov") };
if info.has_pat() { print!(", pat") };
if info.has_pse36() { print!(", pse36") };
if info.has_psn() { print!(", psn") };
if info.has_clflush() { print!(", clflush") };
if info.has_ds() { print!(", ds") };
if info.has_acpi() { print!(", acpi") };
if info.has_mmx() { print!(", mmx") };
if info.has_fxsave_fxstor() { print!(", fxsr") };
if info.has_sse() { print!(", sse") };
if info.has_sse2() { print!(", sse2") };
if info.has_ss() { print!(", ss") };
if info.has_htt() { print!(", ht") };
if info.has_tm() { print!(", tm") };
if info.has_pbe() { print!(", pbe") };
if info.has_sse3() { print!(", sse3") };
if info.has_pclmulqdq() { print!(", pclmulqdq") };
if info.has_ds_area() { print!(", dtes64") };
if info.has_monitor_mwait() { print!(", monitor") };
if info.has_cpl() { print!(", ds_cpl") };
if info.has_vmx() { print!(", vmx") };
if info.has_smx() { print!(", smx") };
if info.has_eist() { print!(", est") };
if info.has_tm2() { print!(", tm2") };
if info.has_ssse3() { print!(", ssse3") };
if info.has_cnxtid() { print!(", cnxtid") };
if info.has_fma() { print!(", fma") };
if info.has_cmpxchg16b() { print!(", cx16") };
if info.has_pdcm() { print!(", pdcm") };
if info.has_pcid() { print!(", pcid") };
if info.has_dca() { print!(", dca") };
if info.has_sse41() { print!(", sse4_1") };
if info.has_sse42() { print!(", sse4_2") };
if info.has_x2apic() { print!(", x2apic") };
if info.has_movbe() { print!(", movbe") };
if info.has_popcnt() { print!(", popcnt") };
if info.has_tsc_deadline() { print!(", tsc_deadline_timer") };
if info.has_aesni() { print!(", aes") };
if info.has_xsave() { print!(", xsave") };
if info.has_oxsave() { print!(", xsaveopt") };
if info.has_avx() { print!(", avx") };
if info.has_f16c() { print!(", f16c") };
if info.has_rdrand() { print!(", rdrand") };
println!("");
}
if let Some(info) = cpuid.get_extended_function_info() {
print!("CPU extended function:");
if info.has_64bit_mode() { print!(" lm") };
if info.has_rdtscp() { print!(", rdtscp") };
if info.has_1gib_pages() { print!(", pdpe1gb") };
if info.has_execute_disable() { print!(", nx") };
if info.has_syscall_sysret() { print!(", syscall") };
if info.has_prefetchw() { print!(", prefetchw") };
if info.has_lzcnt() { print!(", lzcnt") };
if info.has_lahf_sahf() { print!(", lahf_lm") };
if info.has_invariant_tsc() { print!(", constant_tsc") };
println!("");
}
if let Some(info) = cpuid.get_extended_feature_info() {
print!("CPU extended features:");
if info.has_fsgsbase() { print!(" fsgsbase") };
if info.has_tsc_adjust_msr() { print!(", tsc_adjust") };
if info.has_bmi1() { print!(", bmi1") };
if info.has_hle() { print!(", hle") };
if info.has_avx2() { print!(", avx2") };
if info.has_smep() { print!(", smep") };
if info.has_bmi2() { print!(", bmi2") };
if info.has_rep_movsb_stosb() { print!(", erms") };
if info.has_invpcid() { print!(", invpcid") };
if info.has_rtm() { print!(", rtm") };
if info.has_qm() { print!(", qm") };
if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") };
if info.has_mpx() { print!(", mpx") };
println!("");
}
Ok(())
}

View file

@ -0,0 +1,23 @@
use ::arch::x86::paging::ActivePageTable;
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
};
pub unsafe fn init(active_table: &mut ActivePageTable) {
LOCAL_APIC.init(active_table);
}
pub struct LocalApic {
pub address: usize,
pub x2: bool
}
impl LocalApic {
unsafe fn init(&mut self, active_table: &mut ActivePageTable) {
// let efer = Efer::read();
// println!("efer = {:?}", efer);
// flush!();
}
}

View file

@ -1,5 +1,10 @@
use ::arch::x86::paging::ActivePageTable;
pub mod pic; pub mod pic;
pub mod local_apic;
pub mod cpu;
pub fn init() { pub unsafe fn init(active_table: &mut ActivePageTable) {
unsafe { pic::init(); } pic::init();
local_apic::init(active_table);
cpu::cpu_info().expect("cpuid not available");
} }

View file

@ -2,31 +2,47 @@ use ::io::{Io, Pio};
pub static mut MASTER: Pic = Pic::new(0x20); pub static mut MASTER: Pic = Pic::new(0x20);
pub static mut SLAVE: Pic = Pic::new(0xA0); pub static mut SLAVE: Pic = Pic::new(0xA0);
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
pub unsafe fn init() { pub unsafe fn init() {
let wait = || {WAIT_PORT.write(0)};
let master_mask = MASTER.data.read();
let slave_mask = SLAVE.data.read();
// Start initialization // Start initialization
MASTER.cmd.write(0x11); MASTER.cmd.write(0x11); wait();
SLAVE.cmd.write(0x11); SLAVE.cmd.write(0x11); wait();
// Set offsets // Set offsets
MASTER.data.write(0x20); MASTER.data.write(0x20); wait();
SLAVE.data.write(0x28); SLAVE.data.write(0x28); wait();
// Set up cascade // Set up cascade
MASTER.data.write(4); MASTER.data.write(4); wait();
SLAVE.data.write(2); SLAVE.data.write(2); wait();
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
MASTER.data.write(1); MASTER.data.write(1); wait();
SLAVE.data.write(1); SLAVE.data.write(1); wait();
// Unmask interrupts // Unmask interrupts
MASTER.data.write(0); MASTER.data.write(0); wait();
SLAVE.data.write(0); SLAVE.data.write(0); wait();
// Ack remaining interrupts // Ack remaining interrupts
MASTER.ack(); MASTER.ack(); wait();
SLAVE.ack(); SLAVE.ack(); wait();
MASTER.data.write(master_mask); wait();
SLAVE.data.write(slave_mask); wait();
println!("master={:#b}", MASTER.data.read());
println!("slave ={:#b}", SLAVE.data.read());
unsafe { ::arch::x86::interrupt::irq::trigger(1); }
println!("master={:#b}", MASTER.data.read());
println!("slave ={:#b}", SLAVE.data.read());
} }
pub struct Pic { pub struct Pic {

View file

@ -0,0 +1,57 @@
use x86::structures::idt::*;
use super::interrupt::*;
lazy_static! {
static ref IDT: Idt = {
let mut idt = Idt::new();
// set up CPU exceptions
idt.breakpoint.set_handler_fn(exception::breakpoint);
idt.debug.set_handler_fn(exception::debug);
idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable);
idt.breakpoint.set_handler_fn(exception::breakpoint);
idt.overflow.set_handler_fn(exception::overflow);
idt.bound_range_exceeded.set_handler_fn(exception::bound_range);
idt.invalid_opcode.set_handler_fn(exception::invalid_opcode);
idt.device_not_available.set_handler_fn(exception::device_not_available);
idt.double_fault.set_handler_fn(exception::double_fault);
idt.segment_not_present.set_handler_fn(exception::segment_not_present);
idt.stack_segment_fault.set_handler_fn(exception::stack_segment);
idt.general_protection_fault.set_handler_fn(exception::general_protection);
idt.page_fault.set_handler_fn(exception::page_fault);
idt.x87_floating_point.set_handler_fn(exception::x87_fpu);
idt.alignment_check.set_handler_fn(exception::alignment_check);
idt.machine_check.set_handler_fn(exception::machine_check);
idt.simd_floating_point.set_handler_fn(exception::simd);
idt.virtualization.set_handler_fn(exception::virtualization);
// set up IRQs
idt[32].set_handler_fn(irq::pit);
idt[33].set_handler_fn(irq::keyboard);
idt[34].set_handler_fn(irq::cascade);
idt[35].set_handler_fn(irq::com2);
idt[36].set_handler_fn(irq::com1);
idt[37].set_handler_fn(irq::lpt2);
idt[38].set_handler_fn(irq::floppy);
idt[39].set_handler_fn(irq::lpt1);
idt[40].set_handler_fn(irq::rtc);
idt[41].set_handler_fn(irq::pci1);
idt[42].set_handler_fn(irq::pci2);
idt[43].set_handler_fn(irq::pci3);
idt[44].set_handler_fn(irq::mouse);
idt[45].set_handler_fn(irq::fpu);
idt[46].set_handler_fn(irq::ata1);
idt[47].set_handler_fn(irq::ata2);
idt
};
}
// pub fn init(memory_controller: &mut ::memory::MemoryController) {
pub fn init() {
// let double_fault_stack = memory_controller.alloc_stack(1)
// .expect("could not allocate double fault stack");
// println!("DF stack: {:#?}", double_fault_stack);
// flush!();
IDT.load();
}

View file

@ -1,6 +1,51 @@
use x86::structures::idt::*; use x86::structures::idt::*;
use arch::x86::device::pic;
pub unsafe fn 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();
}
}
}
pub unsafe fn acknowledge(irq: usize) {
if irq < 16 {
if irq >= 8 {
pic::SLAVE.mask_clear(irq as u8 - 8);
} else {
pic::MASTER.mask_clear(irq as u8);
}
}
}
interrupt!(pit, {});
interrupt!(keyboard, { interrupt!(keyboard, {
println!("key pressed!"); unsafe { trigger(1); }
println!("IT WOOOOOOOOOORKS WOUHOU!!!!!!");
flush!(); flush!();
unsafe { acknowledge(1); }
}); });
interrupt!(cascade, {});
interrupt!(com2, {});
interrupt!(com1, {});
interrupt!(lpt2, {});
interrupt!(floppy, {});
interrupt!(lpt1, {});
interrupt!(rtc, {});
interrupt!(pci1, {});
interrupt!(pci2, {});
interrupt!(pci3, {});
interrupt!(mouse, {});
interrupt!(fpu, {});
interrupt!(ata1, {});
interrupt!(ata2, {});

View file

@ -1,44 +1,2 @@
use x86::structures::idt::*;
#[macro_use] pub mod exception; #[macro_use] pub mod exception;
#[macro_use] pub mod irq; #[macro_use] pub mod irq;
lazy_static! {
static ref IDT: Idt = {
let mut idt = Idt::new();
// set up CPU exceptions
idt.breakpoint.set_handler_fn(exception::breakpoint);
idt.debug.set_handler_fn(exception::debug);
idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable);
idt.breakpoint.set_handler_fn(exception::breakpoint);
idt.overflow.set_handler_fn(exception::overflow);
idt.bound_range_exceeded.set_handler_fn(exception::bound_range);
idt.invalid_opcode.set_handler_fn(exception::invalid_opcode);
idt.device_not_available.set_handler_fn(exception::device_not_available);
idt.double_fault.set_handler_fn(exception::double_fault);
idt.segment_not_present.set_handler_fn(exception::segment_not_present);
idt.stack_segment_fault.set_handler_fn(exception::stack_segment);
idt.general_protection_fault.set_handler_fn(exception::general_protection);
idt.page_fault.set_handler_fn(exception::page_fault);
idt.x87_floating_point.set_handler_fn(exception::x87_fpu);
idt.alignment_check.set_handler_fn(exception::alignment_check);
idt.machine_check.set_handler_fn(exception::machine_check);
idt.simd_floating_point.set_handler_fn(exception::simd);
idt.virtualization.set_handler_fn(exception::virtualization);
// set up IRQs
idt[33].set_handler_fn(irq::keyboard);
idt
};
}
// pub fn init(memory_controller: &mut ::memory::MemoryController) {
pub fn init() {
// let double_fault_stack = memory_controller.alloc_stack(1)
// .expect("could not allocate double fault stack");
// println!("DF stack: {:#?}", double_fault_stack);
// flush!();
IDT.load();
}

View file

@ -5,9 +5,11 @@ pub mod macros;
pub mod paging; pub mod paging;
pub mod interrupt; pub mod interrupt;
pub mod device; pub mod device;
pub mod idt;
use multiboot2; use multiboot2;
use acpi; use acpi;
use raw_cpuid::CpuId;
#[no_mangle] #[no_mangle]
pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
@ -23,21 +25,20 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
acpi::init().expect("ACPI failed"); acpi::init().expect("ACPI failed");
} }
// set up interrupts
idt::init();
// set up physical allocator // set up physical allocator
::memory::init(&boot_info); ::memory::init(&boot_info);
// set up interrupts
self::interrupt::init();
// set up virtual mapping // set up virtual mapping
let mut active_table = self::paging::init(&boot_info); let mut active_table = paging::init(&boot_info);
// set up heap // set up heap
::allocator::init(&mut active_table); ::allocator::init(&mut active_table);
// pic // set up pic & apic
self::device::init(); device::init(&mut active_table);
// after core has loaded // after core has loaded
::memory::init_noncore(); ::memory::init_noncore();

View file

@ -45,3 +45,10 @@ pub fn halt() -> ! {
unsafe {asm!("hlt" : : : : "volatile")}; unsafe {asm!("hlt" : : : : "volatile")};
} }
} }
/// wait for an io operation to complete
pub fn io_wait() {
unsafe { asm!("jmp 1f\n\t
1:jmp 2f\n\t
2:" : : : : "volatile")}
}

View file

@ -77,8 +77,6 @@ fn check_key_state(key: u8) -> (bool, usize) {
} }
pub fn kbd_callback() { pub fn kbd_callback() {
println!("kbd callback called");
flush!();
static mut SHIFT: bool = false; static mut SHIFT: bool = false;
static mut CTRL: bool = false; static mut CTRL: bool = false;
static mut ALT: bool = false; static mut ALT: bool = false;

View file

@ -19,6 +19,7 @@ extern crate rlibc;
extern crate spin; extern crate spin;
extern crate multiboot2; extern crate multiboot2;
extern crate slab_allocator; extern crate slab_allocator;
extern crate raw_cpuid;
// used by arch/x86, need conditional compilation here // used by arch/x86, need conditional compilation here
extern crate x86; extern crate x86;
@ -44,11 +45,8 @@ pub mod arch;
/// kernel entry point. arch module is responsible for calling this /// kernel entry point. arch module is responsible for calling this
pub fn kmain() -> ! { pub fn kmain() -> ! {
// vga is specific to chipset not cpu
vga::init();
// x86::instructions::interrupts::disable(); // x86::instructions::interrupts::disable();
// x86::instructions::interrupts::int3(); x86::instructions::interrupts::int3();
// x86::instructions::interrupts::enable(); // x86::instructions::interrupts::enable();
// fn stack_overflow() { stack_overflow(); } // fn stack_overflow() { stack_overflow(); }
@ -58,6 +56,10 @@ pub fn kmain() -> ! {
// *(0xdead as *mut u32) = 42; // *(0xdead as *mut u32) = 42;
// }; // };
// vga is specific to chipset not cpu
vga::init();
// loop { keyboard::kbd_callback(); }
loop {} loop {}
} }

View file

@ -199,21 +199,21 @@ impl fmt::Write for Writer {
pub fn init() { pub fn init() {
set_color!(White, Cyan); set_color!(White, Cyan);
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
format_args!("{: ^80}", r#" ,--, "#), // format_args!("{: ^80}", r#" ,--, "#),
format_args!("{: ^80}", r#" ,--.'| ,----, "#), // format_args!("{: ^80}", r#" ,--.'| ,----, "#),
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
format_args!("{: ^80}", r#"; : | | ; | : . ; "#), // format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
format_args!("{: ^80}", r#" ' ; |./__; : "#), // format_args!("{: ^80}", r#" ' ; |./__; : "#),
format_args!("{: ^80}", r#" | : ;| : .' "#), // format_args!("{: ^80}", r#" | : ;| : .' "#),
format_args!("{: ^80}", r#" ' ,/ ; | .' "#), // format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
format_args!("{: ^80}", r#" '--' `---' "#)); // format_args!("{: ^80}", r#" '--' `---' "#));
set_color!(); set_color!();
unsafe { VGA.prompt(); } unsafe { VGA.prompt(); }
unsafe { VGA.flush(); } unsafe { VGA.flush(); }

@ -1 +1 @@
Subproject commit ea8512f4c21c6c84578e04eff1f0b4662f089cd9 Subproject commit 5c33fe133431bb85b86deeff4ec12f17f7ee96cd