code doesnt work anymore but i'm commiting anyway, shoot me
This commit is contained in:
parent
bea6a729fe
commit
a0ad3689f3
30 changed files with 725 additions and 476 deletions
|
|
@ -13,12 +13,12 @@ spin = "0.4"
|
|||
slab_allocator = "0.3.1"
|
||||
multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag
|
||||
x86 = { path = "x86" } # forked for IA32
|
||||
raw-cpuid = { path = "rust-cpuid" }
|
||||
# raw-cpuid = { path = "rust-cpuid" }
|
||||
|
||||
# [dependencies.raw-cpuid]
|
||||
# # need to use github/master because of features not yet on crates.io
|
||||
# git = "https://github.com/gz/rust-cpuid"
|
||||
# features = ["nightly"]
|
||||
[dependencies.raw-cpuid]
|
||||
# need to use github/master because of features not yet on crates.io
|
||||
git = "https://github.com/gz/rust-cpuid"
|
||||
features = ["nightly"]
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.0.0"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ static mut DSDT: DSDT = DSDT {
|
|||
dsdt: None,
|
||||
s5_ptr: 0,
|
||||
slp_typ_a: 0,
|
||||
slp_typ_b: 0
|
||||
slp_typ_b: 0,
|
||||
};
|
||||
|
||||
struct DSDT {
|
||||
|
|
@ -15,7 +15,7 @@ struct DSDT {
|
|||
dsdt: Option<&'static ACPISDTHeader>,
|
||||
s5_ptr: u32,
|
||||
slp_typ_a: u16,
|
||||
slp_typ_b: u16
|
||||
slp_typ_b: u16,
|
||||
}
|
||||
|
||||
impl DSDT {
|
||||
|
|
@ -32,7 +32,9 @@ impl DSDT {
|
|||
let dsdt_end = dsdt_start + self.dsdt.unwrap().length;
|
||||
for addr in dsdt_start..dsdt_end {
|
||||
if check_signature(addr, "_S5_") {
|
||||
if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) && check_signature(addr + 4, "\x12") {
|
||||
if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\"))
|
||||
&& check_signature(addr + 4, "\x12")
|
||||
{
|
||||
return Ok(addr);
|
||||
}
|
||||
}
|
||||
|
|
@ -43,10 +45,18 @@ impl DSDT {
|
|||
fn parse_s5(&mut self) {
|
||||
let ptr = self.s5_ptr + 5;
|
||||
let ptr = ((unsafe { *(ptr as *const u8) } & 0xC0) >> 6) + 2;
|
||||
let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix
|
||||
let ptr = if unsafe { *(ptr as *const u8) } == 0x0A {
|
||||
ptr + 1
|
||||
} else {
|
||||
ptr
|
||||
}; // Skip bytePrefix
|
||||
self.slp_typ_a = (unsafe { *(ptr as *const u8) } as u16) << 10;
|
||||
let ptr = ptr + 1;
|
||||
let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix
|
||||
let ptr = if unsafe { *(ptr as *const u8) } == 0x0A {
|
||||
ptr + 1
|
||||
} else {
|
||||
ptr
|
||||
}; // Skip bytePrefix
|
||||
self.slp_typ_b = (unsafe { *(ptr as *const u8) } as u16) << 10;
|
||||
}
|
||||
}
|
||||
|
|
@ -56,8 +66,8 @@ fn is_init() -> Result <(), &'static str> {
|
|||
true => Ok(()),
|
||||
false => match unsafe { DSDT.dsdt } {
|
||||
Some(_) => Err("Differentiated System Description Pointer (DSDP) is not valid"),
|
||||
None => Err("Differentiated System Description Pointer (DSDP) is not initialized")
|
||||
}
|
||||
None => Err("Differentiated System Description Pointer (DSDP) is not initialized"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,12 @@ struct GenericAddressStructure {
|
|||
bitoffset: u8,
|
||||
accesssize: u8,
|
||||
noused: u32,
|
||||
address: u64
|
||||
address: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct FADT
|
||||
{
|
||||
struct FADT {
|
||||
header: ACPISDTHeader,
|
||||
firmwarectrl: u32,
|
||||
dsdt: u32,
|
||||
|
|
@ -80,7 +79,6 @@ struct FADT
|
|||
x_pmtimerblock: GenericAddressStructure,
|
||||
x_gpe0block: GenericAddressStructure,
|
||||
x_gpe1block: GenericAddressStructure,
|
||||
|
||||
}
|
||||
|
||||
static mut FADT: Option<FADT> = None;
|
||||
|
|
@ -89,10 +87,12 @@ static mut FADT: Option<FADT> = None;
|
|||
/// input param addr is contain in other ptr of rsdt
|
||||
pub fn init(sdt_iter: ACPISDTIter) -> Result<(), &'static str> {
|
||||
for sdt_ptr in sdt_iter {
|
||||
if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic
|
||||
if ACPISDTHeader::valid(sdt_ptr, "FACP") {
|
||||
// Where is "FADT"? Shut up is magic
|
||||
let fadt_tmp: FADT = unsafe { (*(sdt_ptr as *const FADT)).clone() };
|
||||
unsafe { FADT = Some(fadt_tmp.clone()) };
|
||||
if !is_enable()? { // TODO do i have to check if enabled before init ???
|
||||
if !is_enable()? {
|
||||
// TODO do i have to check if enabled before init ???
|
||||
let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST
|
||||
let acpi_enable = fadt_tmp.acpi_enable;
|
||||
cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command
|
||||
|
|
@ -106,7 +106,7 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> {
|
|||
fn is_init() -> Result<FADT, &'static str> {
|
||||
match unsafe { FADT.clone() } {
|
||||
Some(fadt) => Ok(fadt),
|
||||
None => Err("Fixed ACPI Description Table (FADT) is not initialized")
|
||||
None => Err("Fixed ACPI Description Table (FADT) is not initialized"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ impl ACPISDTHeader {
|
|||
|
||||
static mut ACPI: Acpi = Acpi {
|
||||
valid: false,
|
||||
v2: false
|
||||
v2: false,
|
||||
};
|
||||
|
||||
struct Acpi {
|
||||
valid: bool,
|
||||
v2: bool
|
||||
v2: bool,
|
||||
}
|
||||
|
||||
impl Acpi {
|
||||
|
|
@ -58,7 +58,6 @@ impl Acpi {
|
|||
dsdt::init(fadt::dsdtaddr()?)?;
|
||||
self.valid = true;
|
||||
Ok(())
|
||||
|
||||
}
|
||||
fn init(&mut self) -> Result<(), &'static str> {
|
||||
self.v2 = rsdp::init()?;
|
||||
|
|
@ -71,7 +70,9 @@ impl Acpi {
|
|||
}
|
||||
|
||||
fn check_signature(addr: u32, id: &str) -> bool {
|
||||
let signature = match core::str::from_utf8(unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, id.len())}) {
|
||||
let signature = match core::str::from_utf8(unsafe {
|
||||
core::slice::from_raw_parts_mut(addr as *mut u8, id.len())
|
||||
}) {
|
||||
Ok(y) => y,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
|
@ -91,19 +92,23 @@ pub struct ACPISDTIter {
|
|||
pos: usize,
|
||||
width: usize,
|
||||
sdt: u32,
|
||||
len: usize
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl ACPISDTIter {
|
||||
fn new(acpi_sdt: Option<*const ACPISDTHeader>, ptr_len: usize) -> Result <ACPISDTIter, &'static str> {
|
||||
fn new(
|
||||
acpi_sdt: Option<*const ACPISDTHeader>,
|
||||
ptr_len: usize,
|
||||
) -> Result<ACPISDTIter, &'static str> {
|
||||
match acpi_sdt {
|
||||
None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."),
|
||||
Some(ptr) => Ok(ACPISDTIter {
|
||||
pos: 0,
|
||||
width: ptr_len,
|
||||
sdt: ptr as u32 + mem::size_of::<ACPISDTHeader>() as u32,
|
||||
len: (unsafe {(*ptr).length} as usize - mem::size_of::<ACPISDTHeader>()) / ptr_len
|
||||
})
|
||||
len: (unsafe { (*ptr).length } as usize - mem::size_of::<ACPISDTHeader>())
|
||||
/ ptr_len,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +135,6 @@ fn is_init() -> Result <(), &'static str> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Initalized the ACPI module
|
||||
pub fn init() -> Result<(), &'static str> {
|
||||
if let Ok(()) = is_init() {
|
||||
|
|
@ -157,6 +161,13 @@ pub fn shutdown() -> Result <(), &'static str> {
|
|||
/// Display state of ACPI
|
||||
pub fn info() -> Result<(), &'static str> {
|
||||
is_init()?;
|
||||
println!("ACPI STATE:\n {}", if fadt::is_enable()? {"ENABLED"} else {"DISABLED"});
|
||||
println!(
|
||||
"ACPI STATE:\n {}",
|
||||
if fadt::is_enable()? {
|
||||
"ENABLED"
|
||||
} else {
|
||||
"DISABLED"
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::{check_signature,check_checksum};
|
||||
use super::{check_checksum, check_signature};
|
||||
use core::mem;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -31,7 +31,9 @@ pub fn load(addr: u32) -> Result <bool, &'static str> {
|
|||
if check_signature(addr, "RSD PTR ") {
|
||||
let rsdp_tmp: RSDP20 = unsafe { (*(addr as *const RSDP20)).clone() };
|
||||
let revision = rsdp_tmp.rsdp.revision;
|
||||
if (revision == 0 && check_checksum(addr, mem::size_of::<RSDP>())) || (revision == 2 && check_checksum(addr, mem::size_of::<RSDP20>())) {
|
||||
if (revision == 0 && check_checksum(addr, mem::size_of::<RSDP>()))
|
||||
|| (revision == 2 && check_checksum(addr, mem::size_of::<RSDP20>()))
|
||||
{
|
||||
unsafe { RSDPTR = Some(rsdp_tmp) };
|
||||
return Ok(revision == 2);
|
||||
}
|
||||
|
|
@ -44,7 +46,7 @@ fn memory_finding() -> Result <bool, &'static str> {
|
|||
while i < 0x1000000 {
|
||||
i += 8;
|
||||
if let Ok(result) = load(i) {
|
||||
return Ok(result)
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
Err("Can not find Root System Description Pointer (RSDP).")
|
||||
|
|
@ -53,7 +55,7 @@ fn memory_finding() -> Result <bool, &'static str> {
|
|||
fn is_init() -> Result<RSDP20, &'static str> {
|
||||
match unsafe { RSDPTR.clone() } {
|
||||
Some(rsdptr) => Ok(rsdptr),
|
||||
None => Err("Root System Description Pointer (RSDP) is not initialized")
|
||||
None => Err("Root System Description Pointer (RSDP) is not initialized"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,9 @@ use x86::*;
|
|||
use x86::structures::paging::*;
|
||||
use arch::x86::paging::*;
|
||||
|
||||
fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize)
|
||||
{
|
||||
fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) {
|
||||
let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32));
|
||||
let heap_end_page = Page::containing_address(VirtAddr::new(
|
||||
offset as u32 + size as u32 - 1));
|
||||
let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1));
|
||||
|
||||
for page in heap_start_page..heap_end_page + 1 {
|
||||
active_table.map(page, PageTableFlags::WRITABLE);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
extern crate raw_cpuid;
|
||||
|
||||
use core::fmt::{Result};
|
||||
use core::fmt::Result;
|
||||
|
||||
use self::raw_cpuid::CpuId;
|
||||
|
||||
|
|
@ -29,102 +29,260 @@ pub fn cpu_info() -> Result {
|
|||
|
||||
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_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_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_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_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_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_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_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") };
|
||||
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!("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") };
|
||||
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!("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") };
|
||||
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!("");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use ::arch::x86::paging::ActivePageTable;
|
||||
use arch::x86::paging::ActivePageTable;
|
||||
|
||||
pub static mut LOCAL_APIC: LocalApic = LocalApic {
|
||||
address: 0,
|
||||
x2: false
|
||||
x2: false,
|
||||
};
|
||||
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
|
|
@ -11,7 +11,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
|
|||
|
||||
pub struct LocalApic {
|
||||
pub address: usize,
|
||||
pub x2: bool
|
||||
pub x2: bool,
|
||||
}
|
||||
|
||||
impl LocalApic {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use ::arch::x86::paging::ActivePageTable;
|
||||
use arch::x86::paging::ActivePageTable;
|
||||
pub mod pic;
|
||||
pub mod local_apic;
|
||||
pub mod cpu;
|
||||
|
|
|
|||
|
|
@ -1,47 +1,64 @@
|
|||
use ::io::{Io, Pio};
|
||||
use io::{Io, Pio};
|
||||
|
||||
pub static mut MASTER: Pic = Pic::new(0x20);
|
||||
pub static mut SLAVE: Pic = Pic::new(0xA0);
|
||||
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
|
||||
|
||||
pub unsafe fn init() {
|
||||
let wait = || {WAIT_PORT.write(0)};
|
||||
let wait = || WAIT_PORT.write(0);
|
||||
let master_mask = MASTER.data.read();
|
||||
let slave_mask = SLAVE.data.read();
|
||||
|
||||
// Start initialization
|
||||
MASTER.cmd.write(0x11); wait();
|
||||
SLAVE.cmd.write(0x11); wait();
|
||||
MASTER.cmd.write(0x11);
|
||||
wait();
|
||||
SLAVE.cmd.write(0x11);
|
||||
wait();
|
||||
|
||||
// Set offsets
|
||||
MASTER.data.write(0x20); wait();
|
||||
SLAVE.data.write(0x28); wait();
|
||||
MASTER.data.write(0x20);
|
||||
wait();
|
||||
SLAVE.data.write(0x28);
|
||||
wait();
|
||||
|
||||
// Set up cascade
|
||||
MASTER.data.write(4); wait();
|
||||
SLAVE.data.write(2); wait();
|
||||
MASTER.data.write(4);
|
||||
wait();
|
||||
SLAVE.data.write(2);
|
||||
wait();
|
||||
|
||||
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
||||
MASTER.data.write(1); wait();
|
||||
SLAVE.data.write(1); wait();
|
||||
MASTER.data.write(1);
|
||||
wait();
|
||||
SLAVE.data.write(1);
|
||||
wait();
|
||||
|
||||
// Unmask interrupts
|
||||
MASTER.data.write(0); wait();
|
||||
SLAVE.data.write(0); wait();
|
||||
MASTER.data.write(0);
|
||||
wait();
|
||||
SLAVE.data.write(0);
|
||||
wait();
|
||||
|
||||
// Ack remaining interrupts
|
||||
MASTER.ack(); wait();
|
||||
SLAVE.ack(); wait();
|
||||
MASTER.ack();
|
||||
wait();
|
||||
SLAVE.ack();
|
||||
wait();
|
||||
|
||||
MASTER.data.write(master_mask); wait();
|
||||
SLAVE.data.write(slave_mask); wait();
|
||||
MASTER.data.write(master_mask);
|
||||
wait();
|
||||
SLAVE.data.write(slave_mask);
|
||||
wait();
|
||||
|
||||
// disable all irqs
|
||||
MASTER.data.write(!0); wait();
|
||||
SLAVE.data.write(!0); wait();
|
||||
MASTER.data.write(!0);
|
||||
wait();
|
||||
SLAVE.data.write(!0);
|
||||
wait();
|
||||
|
||||
// keyboard active
|
||||
MASTER.mask_clear(1); wait();
|
||||
MASTER.mask_clear(1);
|
||||
wait();
|
||||
|
||||
// asm!("sti");
|
||||
::x86::instructions::interrupts::enable();
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ use x86::instructions::segmentation::set_cs;
|
|||
use x86::instructions::tables::load_tss;
|
||||
use spin::Once;
|
||||
|
||||
static GDT: Once<gdt::Gdt> = Once::new();
|
||||
static TSS: Once<tss::TaskStateSegment> = Once::new();
|
||||
// static GDT: Once<gdt::Gdt> = Once::new();
|
||||
// static TSS: Once<tss::TaskStateSegment> = Once::new();
|
||||
|
||||
pub fn init() {
|
||||
// let tss = tss::TaskStateSegment::new();
|
||||
let tss = TSS.call_once(|| {
|
||||
let mut tss = tss::TaskStateSegment::new();
|
||||
tss
|
||||
});
|
||||
// let tss = TSS.call_once(|| {
|
||||
// let mut tss = tss::TaskStateSegment::new();
|
||||
// tss
|
||||
// });
|
||||
|
||||
// let mut code_selector = gdt::SegmentSelector(0);
|
||||
// let mut tss_selector = gdt::SegmentSelector(0);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// https://wiki.osdev.org/Exceptions
|
||||
|
||||
use ::arch::x86::pti;
|
||||
use arch::x86::pti;
|
||||
|
||||
macro_rules! exception {
|
||||
($name:ident, $func:block) => {
|
||||
|
|
@ -62,8 +62,9 @@ exception_err!(stack_segment, {});
|
|||
exception_err!(general_protection, {});
|
||||
|
||||
pub extern "x86-interrupt" fn page_fault(
|
||||
stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode)
|
||||
{
|
||||
stack_frame: &mut ExceptionStackFrame,
|
||||
code: PageFaultErrorCode,
|
||||
) {
|
||||
println!("Exception: page_fault");
|
||||
println!("Error code: {:#b}", code);
|
||||
println!("{:#?}", stack_frame);
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
#[macro_use] pub mod exception;
|
||||
#[macro_use] pub mod irq;
|
||||
#[macro_use]
|
||||
pub mod exception;
|
||||
#[macro_use]
|
||||
pub mod irq;
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ pub mod interrupt;
|
|||
pub mod device;
|
||||
pub mod pti;
|
||||
|
||||
pub mod gdt;
|
||||
// pub mod gdt;
|
||||
pub mod idt;
|
||||
|
||||
use multiboot2;
|
||||
use acpi;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
|
||||
pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
|
||||
// parse multiboot2 info
|
||||
let boot_info = multiboot2::load(multiboot_info_addr);
|
||||
|
||||
|
|
@ -26,24 +26,26 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
|
|||
acpi::init().expect("ACPI failed");
|
||||
}
|
||||
|
||||
// fill and load idt (exceptions + irqs)
|
||||
idt::init();
|
||||
|
||||
// set up physical allocator
|
||||
::memory::init(&boot_info);
|
||||
|
||||
// set up virtual mapping
|
||||
let mut active_table = paging::init(&boot_info);
|
||||
|
||||
asm!("hlt");
|
||||
|
||||
// set up heap
|
||||
::allocator::init(&mut active_table);
|
||||
|
||||
// set up memory segmentation
|
||||
// gdt::init();
|
||||
|
||||
// set up interrupts
|
||||
idt::init();
|
||||
|
||||
// set up pic & apic
|
||||
device::init(&mut active_table);
|
||||
|
||||
// fill and load gdt
|
||||
// gdt::init();
|
||||
|
||||
// primary CPU entry point
|
||||
::kmain();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ impl Mapper {
|
|||
}
|
||||
|
||||
/// virtual addr to physical addr translation
|
||||
pub fn translate(&self, virtual_address: VirtAddr) -> Option<PhysAddr>
|
||||
{
|
||||
pub fn translate(&self, virtual_address: VirtAddr) -> Option<PhysAddr> {
|
||||
let offset = virtual_address.as_u32() % PAGE_SIZE as u32;
|
||||
self.translate_page(Page::containing_address(virtual_address))
|
||||
.map(|frame| frame.start_address() + offset)
|
||||
|
|
@ -58,29 +57,25 @@ impl Mapper {
|
|||
}
|
||||
|
||||
/// map a virtual page to a physical frame in the page tables
|
||||
pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags)
|
||||
{
|
||||
pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags) {
|
||||
let p2 = self.p2_mut();
|
||||
let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())));
|
||||
assert!(p1[page.p1_index()].is_unused());
|
||||
p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT);
|
||||
}
|
||||
|
||||
pub fn map(&mut self, page: Page, flags: PageTableFlags)
|
||||
{
|
||||
pub fn map(&mut self, page: Page, flags: PageTableFlags) {
|
||||
let frame = ::memory::allocate_frames(1).expect("out of frames");
|
||||
self.map_to(page, frame, flags)
|
||||
}
|
||||
|
||||
pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags)
|
||||
{
|
||||
pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags) {
|
||||
let virt_addr = VirtAddr::new(frame.start_address().as_u32());
|
||||
let page = Page::containing_address(virt_addr);
|
||||
self.map_to(page, frame, flags);
|
||||
}
|
||||
|
||||
pub fn unmap(&mut self, page: Page)
|
||||
{
|
||||
pub fn unmap(&mut self, page: Page) {
|
||||
assert!(self.translate(page.start_address()).is_some());
|
||||
|
||||
let p1 = self.p2_mut()
|
||||
|
|
|
|||
|
|
@ -51,11 +51,13 @@ impl ActivePageTable {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with<F>(&mut self,
|
||||
pub fn with<F>(
|
||||
&mut self,
|
||||
table: &mut InactivePageTable,
|
||||
temporary_page: &mut temporary_page::TemporaryPage,
|
||||
f: F)
|
||||
where F: FnOnce(&mut Mapper)
|
||||
f: F,
|
||||
) where
|
||||
F: FnOnce(&mut Mapper),
|
||||
{
|
||||
let (cr3_back, _cr3flags_back) = Cr3::read();
|
||||
|
||||
|
|
@ -63,7 +65,10 @@ impl ActivePageTable {
|
|||
let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self);
|
||||
|
||||
// overwrite recursive map
|
||||
self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
||||
self.p2_mut()[1023].set(
|
||||
table.p2_frame.clone(),
|
||||
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
|
||||
);
|
||||
tlb::flush_all();
|
||||
|
||||
// execute f in the new context
|
||||
|
|
@ -74,11 +79,12 @@ impl ActivePageTable {
|
|||
}
|
||||
|
||||
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
|
||||
|
||||
let (p2_frame, cr3_flags) = Cr3::read();
|
||||
let old_table = InactivePageTable { p2_frame };
|
||||
|
||||
unsafe { Cr3::write(new_table.p2_frame, cr3_flags); }
|
||||
unsafe {
|
||||
Cr3::write(new_table.p2_frame, cr3_flags);
|
||||
}
|
||||
|
||||
old_table
|
||||
}
|
||||
|
|
@ -89,39 +95,44 @@ pub struct InactivePageTable {
|
|||
}
|
||||
|
||||
impl InactivePageTable {
|
||||
pub fn new(frame: PhysFrame,
|
||||
pub fn new(
|
||||
frame: PhysFrame,
|
||||
active_table: &mut ActivePageTable,
|
||||
temporary_page: &mut TemporaryPage)
|
||||
-> InactivePageTable {
|
||||
temporary_page: &mut TemporaryPage,
|
||||
) -> InactivePageTable {
|
||||
{
|
||||
let table = temporary_page.map_table_frame(frame.clone(), active_table);
|
||||
|
||||
table.zero();
|
||||
// set up recursive mapping for the table
|
||||
table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE)
|
||||
table[1023].set(
|
||||
frame.clone(),
|
||||
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
|
||||
)
|
||||
}
|
||||
temporary_page.unmap(active_table);
|
||||
InactivePageTable { p2_frame: frame }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
|
||||
{
|
||||
pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable {
|
||||
let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe });
|
||||
let mut active_table = unsafe { ActivePageTable::new() };
|
||||
let mut new_table = {
|
||||
let frame = ::memory::allocate_frames(1).expect("no more frames");
|
||||
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
asm!("hlt");
|
||||
}
|
||||
|
||||
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
||||
|
||||
// id map vga buffer
|
||||
let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
|
||||
mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE);
|
||||
|
||||
let elf_sections_tag = boot_info.elf_sections_tag()
|
||||
let elf_sections_tag = boot_info
|
||||
.elf_sections_tag()
|
||||
.expect("Memory map tag required");
|
||||
|
||||
// id map kernel sections
|
||||
|
|
@ -129,24 +140,26 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
|
|||
if !section.is_allocated() {
|
||||
continue;
|
||||
}
|
||||
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
|
||||
"sections need to be page aligned");
|
||||
assert!(
|
||||
section.start_address() % PAGE_SIZE as u64 == 0,
|
||||
"sections need to be page aligned"
|
||||
);
|
||||
|
||||
let flags = elf_to_pagetable_flags(§ion.flags());
|
||||
let start_frame = PhysFrame::containing_address(
|
||||
PhysAddr::new(section.start_address() as u32));
|
||||
let end_frame = PhysFrame::containing_address(
|
||||
PhysAddr::new(section.end_address() as u32 - 1));
|
||||
let start_frame =
|
||||
PhysFrame::containing_address(PhysAddr::new(section.start_address() as u32));
|
||||
let end_frame =
|
||||
PhysFrame::containing_address(PhysAddr::new(section.end_address() as u32 - 1));
|
||||
for frame in start_frame..end_frame + 1 {
|
||||
mapper.identity_map(frame, flags);
|
||||
}
|
||||
}
|
||||
|
||||
// id map multiboot
|
||||
let multiboot_start = PhysFrame::containing_address(
|
||||
PhysAddr::new(boot_info.start_address() as u32));
|
||||
let multiboot_end = PhysFrame::containing_address(
|
||||
PhysAddr::new(boot_info.end_address() as u32 - 1));
|
||||
let multiboot_start =
|
||||
PhysFrame::containing_address(PhysAddr::new(boot_info.start_address() as u32));
|
||||
let multiboot_end =
|
||||
PhysFrame::containing_address(PhysAddr::new(boot_info.end_address() as u32 - 1));
|
||||
for frame in multiboot_start..multiboot_end + 1 {
|
||||
mapper.identity_map(frame, PageTableFlags::PRESENT);
|
||||
}
|
||||
|
|
@ -154,17 +167,15 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
|
|||
|
||||
let old_table = active_table.switch(new_table);
|
||||
|
||||
let old_p2_page = Page::containing_address(
|
||||
VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
|
||||
let old_p2_page =
|
||||
Page::containing_address(VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
|
||||
|
||||
active_table.unmap(old_p2_page);
|
||||
|
||||
active_table
|
||||
}
|
||||
|
||||
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags)
|
||||
-> PageTableFlags
|
||||
{
|
||||
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) -> PageTableFlags {
|
||||
use multiboot2::ElfSectionFlags;
|
||||
|
||||
let mut flags = PageTableFlags::empty();
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
use x86::structures::paging::*;
|
||||
|
||||
pub trait RecTable
|
||||
{
|
||||
pub trait RecTable {
|
||||
fn next_table_address(&self, index: usize) -> Option<u32>;
|
||||
fn next_table(&self, index: usize) -> Option<&PageTable>;
|
||||
fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>;
|
||||
fn next_table_create(&mut self,
|
||||
index: usize)
|
||||
-> &mut PageTable;
|
||||
fn next_table_create(&mut self, index: usize) -> &mut PageTable;
|
||||
}
|
||||
|
||||
impl RecTable for PageTable
|
||||
{
|
||||
impl RecTable for PageTable {
|
||||
fn next_table_address(&self, index: usize) -> Option<u32> {
|
||||
let entry_flags = self[index].flags();
|
||||
if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) {
|
||||
if entry_flags.contains(PageTableFlags::PRESENT)
|
||||
&& !entry_flags.contains(PageTableFlags::HUGE_PAGE)
|
||||
{
|
||||
let table_address = self as *const _ as usize;
|
||||
Some((table_address << 10 | index << 12) as u32)
|
||||
} else {
|
||||
|
|
@ -32,16 +30,17 @@ impl RecTable for PageTable
|
|||
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||
}
|
||||
|
||||
fn next_table_create(&mut self,
|
||||
index: usize) -> &mut PageTable
|
||||
{
|
||||
fn next_table_create(&mut self, index: usize) -> &mut PageTable {
|
||||
if self.next_table(index).is_none() {
|
||||
assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
|
||||
"mapping code does not support huge pages");
|
||||
let frame = ::memory::allocate_frames(1)
|
||||
.expect("out of memory");
|
||||
assert!(
|
||||
!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
|
||||
"mapping code does not support huge pages"
|
||||
);
|
||||
let frame = ::memory::allocate_frames(1).expect("out of memory");
|
||||
self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
||||
self.next_table_mut(index).expect("next_table_mut gave None").zero()
|
||||
self.next_table_mut(index)
|
||||
.expect("next_table_mut gave None")
|
||||
.zero()
|
||||
}
|
||||
self.next_table_mut(index).expect("no next table 2")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,22 +7,23 @@ pub struct TemporaryPage {
|
|||
}
|
||||
|
||||
impl TemporaryPage {
|
||||
pub fn new(page: Page) -> TemporaryPage
|
||||
{
|
||||
pub fn new(page: Page) -> TemporaryPage {
|
||||
TemporaryPage { page: page }
|
||||
}
|
||||
|
||||
/// Maps the temporary page to the given frame in the active table.
|
||||
/// Returns the start address of the temporary page.
|
||||
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable)
|
||||
-> VirtAddr
|
||||
{
|
||||
assert!(active_table.translate_page(self.page).is_none(),
|
||||
"temporary page is already mapped");
|
||||
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) -> VirtAddr {
|
||||
assert!(
|
||||
active_table.translate_page(self.page).is_none(),
|
||||
"temporary page is already mapped"
|
||||
);
|
||||
active_table.map_to(self.page, frame, PageTableFlags::WRITABLE);
|
||||
// this kind of check should be done in a test routine
|
||||
assert!(active_table.translate_page(self.page).is_some(),
|
||||
"temporary page was not mapped");
|
||||
assert!(
|
||||
active_table.translate_page(self.page).is_some(),
|
||||
"temporary page was not mapped"
|
||||
);
|
||||
self.page.start_address()
|
||||
}
|
||||
|
||||
|
|
@ -33,10 +34,11 @@ impl TemporaryPage {
|
|||
|
||||
/// Maps the temporary page to the given page table frame in the active
|
||||
/// table. Returns a reference to the now mapped table.
|
||||
pub fn map_table_frame(&mut self,
|
||||
pub fn map_table_frame(
|
||||
&mut self,
|
||||
frame: PhysFrame,
|
||||
active_table: &mut ActivePageTable)
|
||||
-> &mut PageTable {
|
||||
active_table: &mut ActivePageTable,
|
||||
) -> &mut PageTable {
|
||||
unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
|
|||
|
||||
let new_esp = new - offset_esp;
|
||||
|
||||
ptr::copy_nonoverlapping(
|
||||
old_esp as *const u8,
|
||||
new_esp as *mut u8,
|
||||
offset_esp
|
||||
);
|
||||
ptr::copy_nonoverlapping(old_esp as *const u8, new_esp as *mut u8, offset_esp);
|
||||
|
||||
// switch the esp with the new one
|
||||
asm!("" : : "{esp}"(new_esp) : : "intel", "volatile");
|
||||
|
|
@ -47,13 +43,19 @@ pub unsafe fn map() {
|
|||
// }
|
||||
|
||||
// Switch to per-context stack
|
||||
switch_stack(PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), PTI_CONTEXT_STACK);
|
||||
switch_stack(
|
||||
PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(),
|
||||
PTI_CONTEXT_STACK,
|
||||
);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn unmap() {
|
||||
// Switch to per-CPU stack
|
||||
switch_stack(PTI_CONTEXT_STACK, PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len());
|
||||
switch_stack(
|
||||
PTI_CONTEXT_STACK,
|
||||
PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(),
|
||||
);
|
||||
|
||||
// {
|
||||
// let mut active_table = unsafe { ActivePageTable::new() };
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ pub fn acpi_info() -> Result <(), &'static str> {
|
|||
|
||||
/// Dump control registers
|
||||
pub fn regs() -> Result<(), &'static str> {
|
||||
use ::x86::registers::control::*;
|
||||
use x86::registers::control::*;
|
||||
println!("cr0 = {:?}", Cr0::read());
|
||||
println!("cr3 = {:?}", Cr3::read());
|
||||
println!("cr4 = {:?}", Cr4::read());
|
||||
|
|
@ -189,7 +189,7 @@ pub fn regs() -> Result <(), &'static str> {
|
|||
|
||||
/// Dump cpu info, should add power management info
|
||||
pub fn cpu() -> Result<(), &'static str> {
|
||||
use ::arch::x86::device::cpu;
|
||||
use arch::x86::device::cpu;
|
||||
cpu::cpu_info().expect("cpu info not available");
|
||||
flush!();
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ pub fn halt() -> ! {
|
|||
|
||||
/// wait for an io operation to complete
|
||||
pub fn io_wait() {
|
||||
unsafe { asm!("jmp 1f\n\t
|
||||
unsafe {
|
||||
asm!("jmp 1f\n\t
|
||||
1:jmp 2f\n\t
|
||||
2:" : : : : "volatile")}
|
||||
2:" : : : : "volatile")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ pub use self::pio::*;
|
|||
use core::ops::{BitAnd, BitOr, Not};
|
||||
|
||||
pub trait Io {
|
||||
type Value: Copy + PartialEq + BitAnd<Output = Self::Value> + BitOr<Output = Self::Value> + Not<Output = Self::Value>;
|
||||
type Value: Copy
|
||||
+ PartialEq
|
||||
+ BitAnd<Output = Self::Value>
|
||||
+ BitOr<Output = Self::Value>
|
||||
+ Not<Output = Self::Value>;
|
||||
|
||||
fn read(&self) -> Self::Value;
|
||||
fn write(&mut self, value: Self::Value);
|
||||
|
|
|
|||
|
|
@ -84,25 +84,24 @@ pub fn kbd_callback() {
|
|||
if (control & 1) == 1 {
|
||||
let scancode = cpuio::inb(0x60);
|
||||
let (is_release, scancode) = check_key_state(scancode);
|
||||
unsafe {//TODO remove unsafe
|
||||
unsafe {
|
||||
//TODO remove unsafe
|
||||
match self::KEYMAP_US.get(scancode as usize) {
|
||||
Some(b"\0\0") => {
|
||||
match scancode {
|
||||
0x2A | 0x36 => {SHIFT = !is_release},
|
||||
0x38 => {ALT = !is_release},
|
||||
0x1D => {CTRL = !is_release},
|
||||
Some(b"\0\0") => match scancode {
|
||||
0x2A | 0x36 => SHIFT = !is_release,
|
||||
0x38 => ALT = !is_release,
|
||||
0x1D => CTRL = !is_release,
|
||||
0x0E if !is_release => {
|
||||
vga::VGA.backspace();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
Some(ascii) if !is_release => {
|
||||
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
||||
vga::VGA.keypress(sym);
|
||||
},
|
||||
Some(_) => {},
|
||||
None =>{},
|
||||
}
|
||||
Some(_) => {}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,28 +7,28 @@
|
|||
#![feature(ptr_internals)]
|
||||
#![feature(asm)]
|
||||
#![feature(thread_local)]
|
||||
|
||||
// home made heap
|
||||
#![feature(alloc)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(global_allocator)]
|
||||
|
||||
// x86 specific
|
||||
#![feature(abi_x86_interrupt)]
|
||||
|
||||
extern crate rlibc;
|
||||
extern crate alloc;
|
||||
extern crate spin;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate multiboot2;
|
||||
extern crate slab_allocator;
|
||||
extern crate raw_cpuid;
|
||||
extern crate rlibc;
|
||||
extern crate slab_allocator;
|
||||
extern crate spin;
|
||||
|
||||
// used by arch/x86, need conditional compilation here
|
||||
extern crate x86;
|
||||
|
||||
/// 80x25 terminal driver
|
||||
#[macro_use] pub mod vga;
|
||||
#[macro_use]
|
||||
pub mod vga;
|
||||
/// PS/2 detection and processing
|
||||
pub mod keyboard;
|
||||
/// simplisitc kernel commands
|
||||
|
|
@ -45,9 +45,10 @@ pub mod memory;
|
|||
/// arch specific entry points
|
||||
pub mod arch;
|
||||
|
||||
/// kernel entry point. arch module is responsible for calling this
|
||||
/// kernel entry point. arch module is responsible for
|
||||
/// calling this once the core has loaded
|
||||
pub fn kmain() -> ! {
|
||||
// core is loaded now
|
||||
// heap avalaible for tracking free'd frames
|
||||
memory::init_noncore();
|
||||
|
||||
// x86::instructions::interrupts::int3();
|
||||
|
|
@ -66,12 +67,13 @@ pub fn kmain() -> ! {
|
|||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"] #[no_mangle]
|
||||
pub extern fn eh_personality() {}
|
||||
#[lang = "eh_personality"]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn eh_personality() {}
|
||||
|
||||
#[lang = "panic_fmt"] #[no_mangle]
|
||||
pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32)
|
||||
-> ! {
|
||||
#[lang = "panic_fmt"]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
|
||||
println!("PANIC: {}", fmt);
|
||||
println!("FILE: {}", file);
|
||||
println!("LINE: {}", line);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use multiboot2::{MemoryAreaIter, MemoryArea};
|
||||
use multiboot2::{MemoryArea, MemoryAreaIter};
|
||||
use x86::*;
|
||||
use x86::structures::paging::PhysFrame;
|
||||
use super::FrameAllocator;
|
||||
|
|
@ -14,21 +14,21 @@ pub struct BumpFrameAllocator {
|
|||
}
|
||||
|
||||
impl BumpFrameAllocator {
|
||||
pub fn new(kernel_start: usize, kernel_end: usize,
|
||||
multiboot_start: usize, multiboot_end: usize,
|
||||
memory_areas: MemoryAreaIter) -> BumpFrameAllocator {
|
||||
pub fn new(
|
||||
kernel_start: usize,
|
||||
kernel_end: usize,
|
||||
multiboot_start: usize,
|
||||
multiboot_end: usize,
|
||||
memory_areas: MemoryAreaIter,
|
||||
) -> BumpFrameAllocator {
|
||||
let mut allocator = BumpFrameAllocator {
|
||||
next_free_frame: PhysFrame { number: 0 },
|
||||
current_area: None,
|
||||
areas: memory_areas,
|
||||
kernel_start: PhysFrame::containing_address(
|
||||
PhysAddr::new(kernel_start as u32)),
|
||||
kernel_end: PhysFrame::containing_address(
|
||||
PhysAddr::new(kernel_end as u32)),
|
||||
multiboot_start: PhysFrame::containing_address(
|
||||
PhysAddr::new(multiboot_start as u32)),
|
||||
multiboot_end: PhysFrame::containing_address(
|
||||
PhysAddr::new(multiboot_end as u32)),
|
||||
kernel_start: PhysFrame::containing_address(PhysAddr::new(kernel_start as u32)),
|
||||
kernel_end: PhysFrame::containing_address(PhysAddr::new(kernel_end as u32)),
|
||||
multiboot_start: PhysFrame::containing_address(PhysAddr::new(multiboot_start as u32)),
|
||||
multiboot_end: PhysFrame::containing_address(PhysAddr::new(multiboot_end as u32)),
|
||||
};
|
||||
allocator.choose_next_area();
|
||||
allocator
|
||||
|
|
@ -36,13 +36,16 @@ impl BumpFrameAllocator {
|
|||
|
||||
fn choose_next_area(&mut self) {
|
||||
// get next area with free frames
|
||||
self.current_area = self.areas.clone().filter(|area| {
|
||||
self.current_area = self.areas
|
||||
.clone()
|
||||
.filter(|area| {
|
||||
area.end_address() >= self.next_free_frame.start_address().as_u32() as usize
|
||||
}).min_by_key(|area| area.start_address());
|
||||
})
|
||||
.min_by_key(|area| area.start_address());
|
||||
|
||||
if let Some(area) = self.current_area {
|
||||
let start_frame = PhysFrame::containing_address(
|
||||
PhysAddr::new(area.start_address() as u32));
|
||||
let start_frame =
|
||||
PhysFrame::containing_address(PhysAddr::new(area.start_address() as u32));
|
||||
if self.next_free_frame < start_frame {
|
||||
self.next_free_frame = start_frame;
|
||||
}
|
||||
|
|
@ -52,22 +55,32 @@ impl BumpFrameAllocator {
|
|||
|
||||
impl FrameAllocator for BumpFrameAllocator {
|
||||
fn allocate_frames(&mut self, count: usize) -> Option<PhysFrame> {
|
||||
if count == 0 { return None };
|
||||
if count == 0 {
|
||||
return None;
|
||||
};
|
||||
if let Some(area) = self.current_area {
|
||||
let start_frame = PhysFrame { number: self.next_free_frame.number };
|
||||
let end_frame = PhysFrame { number: self.next_free_frame.number + count as u32 - 1 };
|
||||
let start_frame = PhysFrame {
|
||||
number: self.next_free_frame.number,
|
||||
};
|
||||
let end_frame = PhysFrame {
|
||||
number: self.next_free_frame.number + count as u32 - 1,
|
||||
};
|
||||
|
||||
let current_area_last_frame = PhysFrame::containing_address(
|
||||
PhysAddr::new(area.end_address() as u32));
|
||||
let current_area_last_frame =
|
||||
PhysFrame::containing_address(PhysAddr::new(area.end_address() as u32));
|
||||
if end_frame > current_area_last_frame {
|
||||
// all frames are taken in this area
|
||||
self.choose_next_area();
|
||||
} else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) {
|
||||
} else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end)
|
||||
|| (end_frame >= self.kernel_start && end_frame <= self.kernel_end)
|
||||
{
|
||||
// frame used by kernel
|
||||
self.next_free_frame = PhysFrame {
|
||||
number: self.kernel_end.number + 1,
|
||||
};
|
||||
} else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end) || (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end) {
|
||||
} else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end)
|
||||
|| (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end)
|
||||
{
|
||||
// frame used by multiboot
|
||||
self.next_free_frame = PhysFrame {
|
||||
number: self.multiboot_end.number + 1,
|
||||
|
|
@ -85,7 +98,11 @@ impl FrameAllocator for BumpFrameAllocator {
|
|||
|
||||
fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) {
|
||||
// bump doesnt deallocate, must be used inside of a recycler
|
||||
println!("lost frames {:#x} ({})", frame.start_address().as_u32(), count);
|
||||
println!(
|
||||
"lost frames {:#x} ({})",
|
||||
frame.start_address().as_u32(),
|
||||
count
|
||||
);
|
||||
// unimplemented!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,20 +24,27 @@ pub fn init(boot_info: &multiboot2::BootInformation) {
|
|||
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
|
||||
let memory_map_tag = boot_info.memory_map_tag().unwrap();
|
||||
|
||||
let kernel_start = elf_sections_tag.sections()
|
||||
let kernel_start = elf_sections_tag
|
||||
.sections()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.start_address())
|
||||
.min().unwrap();
|
||||
.min()
|
||||
.unwrap();
|
||||
|
||||
let kernel_end = elf_sections_tag.sections()
|
||||
let kernel_end = elf_sections_tag
|
||||
.sections()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.start_address() + s.size())
|
||||
.max().unwrap();
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
let bump_allocator = BumpFrameAllocator::new(
|
||||
kernel_start as usize, kernel_end as usize,
|
||||
boot_info.start_address(), boot_info.end_address(),
|
||||
memory_map_tag.memory_areas());
|
||||
kernel_start as usize,
|
||||
kernel_end as usize,
|
||||
boot_info.start_address(),
|
||||
boot_info.end_address(),
|
||||
memory_map_tag.memory_areas(),
|
||||
);
|
||||
|
||||
let frame_allocator = RecycleAllocator::new(bump_allocator);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ macro_rules! set_color {
|
|||
|
||||
pub fn print(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
unsafe { self::VGA.write_fmt(args).unwrap(); }
|
||||
unsafe {
|
||||
self::VGA.write_fmt(args).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
extern crate core;
|
||||
|
|
@ -51,7 +53,8 @@ const BUFFER_COLS: usize = 80 * 2;
|
|||
pub struct Writer {
|
||||
pub buffer_pos: usize,
|
||||
pub color_code: ColorCode,
|
||||
buffer: [u8; BUFFER_ROWS * BUFFER_COLS], command: [u8; 10],
|
||||
buffer: [u8; BUFFER_ROWS * BUFFER_COLS],
|
||||
command: [u8; 10],
|
||||
command_len: usize,
|
||||
}
|
||||
|
||||
|
|
@ -81,12 +84,10 @@ impl Writer {
|
|||
}
|
||||
|
||||
pub fn get_command(&self) -> Result<&str, &'static str> {
|
||||
|
||||
match core::str::from_utf8(&self.command) {
|
||||
Ok(y) => Ok(&y[..self.command_len]),
|
||||
Err(_) => Err("Command is not utf8 char")
|
||||
Err(_) => Err("Command is not utf8 char"),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn keypress(&mut self, ascii: u8) {
|
||||
|
|
@ -108,7 +109,9 @@ impl Writer {
|
|||
_ if self.command_len >= 10 => (),
|
||||
byte if self.command_len == 0 && byte == b' ' => (),
|
||||
byte => {
|
||||
if self.command_len >= 10 { return };
|
||||
if self.command_len >= 10 {
|
||||
return;
|
||||
};
|
||||
self.command[self.command_len] = byte;
|
||||
self.write_byte(byte);
|
||||
self.command_len += 1;
|
||||
|
|
@ -130,7 +133,6 @@ impl Writer {
|
|||
let i = self.buffer_pos;
|
||||
|
||||
match byte {
|
||||
|
||||
b'\n' => {
|
||||
let current_line = self.buffer_pos / (BUFFER_COLS);
|
||||
self.buffer_pos = (current_line + 1) * BUFFER_COLS;
|
||||
|
|
@ -199,7 +201,8 @@ impl fmt::Write for Writer {
|
|||
|
||||
pub fn init() {
|
||||
set_color!(White, Cyan);
|
||||
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
print!(
|
||||
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
format_args!("{: ^80}", r#" ,--, "#),
|
||||
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
||||
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
||||
|
|
@ -213,8 +216,13 @@ pub fn init() {
|
|||
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
||||
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
||||
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
||||
format_args!("{: ^80}", r#" '--' `---' "#));
|
||||
format_args!("{: ^80}", r#" '--' `---' "#)
|
||||
);
|
||||
set_color!();
|
||||
unsafe { VGA.prompt(); }
|
||||
unsafe { VGA.flush(); }
|
||||
unsafe {
|
||||
VGA.prompt();
|
||||
}
|
||||
unsafe {
|
||||
VGA.flush();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue