Add rustfmt from relibc and apply it with cargo fmt

This commit is contained in:
Jeremy Soller
2024-01-17 13:52:01 -07:00
parent 73897bd83d
commit 45f1c4e29e
166 changed files with 7353 additions and 3851 deletions
+23 -14
View File
@@ -1,8 +1,6 @@
use rustc_cfg::Cfg;
use std::{env, path::Path, process::Command};
use toml::Table;
use std::env;
use std::path::Path;
use std::process::Command;
fn parse_kconfig(arch: &str) -> Option<()> {
println!("cargo:rerun-if-changed=config.toml");
@@ -14,9 +12,16 @@ fn parse_kconfig(arch: &str) -> Option<()> {
let config_str = std::fs::read_to_string("config.toml").unwrap();
let root: Table = toml::from_str(&config_str).unwrap();
let altfeatures = root.get("arch")?.as_table().unwrap()
.get(arch)?.as_table().unwrap()
.get("features")?.as_table().unwrap();
let altfeatures = root
.get("arch")?
.as_table()
.unwrap()
.get(arch)?
.as_table()
.unwrap()
.get("features")?
.as_table()
.unwrap();
for (name, value) in altfeatures {
let choice = value.as_str().unwrap();
@@ -45,30 +50,34 @@ fn main() {
.target("aarch64-unknown-redox")
.compile("early_init");
*/
},
}
"x86" => {
println!("cargo:rerun-if-changed=src/asm/x86/trampoline.asm");
let status = Command::new("nasm")
.arg("-f").arg("bin")
.arg("-o").arg(format!("{}/trampoline", out_dir))
.arg("-f")
.arg("bin")
.arg("-o")
.arg(format!("{}/trampoline", out_dir))
.arg("src/asm/x86/trampoline.asm")
.status()
.expect("failed to run nasm");
if ! status.success() {
if !status.success() {
panic!("nasm failed with exit status {}", status);
}
},
}
"x86_64" => {
println!("cargo:rerun-if-changed=src/asm/x86_64/trampoline.asm");
let status = Command::new("nasm")
.arg("-f").arg("bin")
.arg("-o").arg(format!("{}/trampoline", out_dir))
.arg("-f")
.arg("bin")
.arg("-o")
.arg(format!("{}/trampoline", out_dir))
.arg("src/asm/x86_64/trampoline.asm")
.status()
.expect("failed to run nasm");
if ! status.success() {
if !status.success() {
panic!("nasm failed with exit status {}", status);
}
}
+21
View File
@@ -0,0 +1,21 @@
blank_lines_lower_bound = 0
blank_lines_upper_bound = 1
brace_style = "SameLineWhere"
disable_all_formatting = false
edition = "2018"
empty_item_single_line = true
fn_single_line = false
force_explicit_abi = true
format_strings = false
hard_tabs = false
hide_parse_errors = false
imports_granularity = "Crate"
imports_indent = "Block"
imports_layout = "Mixed"
indent_style = "Block"
max_width = 100
newline_style = "Unix"
skip_children = false
tab_spaces = 4
trailing_comma = "Vertical"
where_single_line = false
+31 -13
View File
@@ -2,12 +2,12 @@ use core::{mem, ptr};
use core::ptr::{read_volatile, write_volatile};
use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags};
use crate::paging::entry::EntryFlags;
use crate::{
memory::Frame,
paging::{entry::EntryFlags, KernelMapper, PageFlags, PhysicalAddress},
};
use super::sdt::Sdt;
use super::{ACPI_TABLE, find_sdt};
use super::{find_sdt, sdt::Sdt, ACPI_TABLE};
#[repr(packed)]
#[derive(Clone, Copy, Debug, Default)]
@@ -32,7 +32,7 @@ pub struct Hpet {
pub hpet_number: u8,
pub min_periodic_clk_tick: u16,
pub oem_attribute: u8
pub oem_attribute: u8,
}
impl Hpet {
@@ -75,13 +75,21 @@ impl GenericAddressStructure {
mapper
.get_mut()
.expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.expect(
"KernelMapper locked re-entrant while mapping memory for GenericAddressStructure",
)
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new()
.write(true)
.custom_flag(EntryFlags::NO_CACHE.bits(), true),
)
.expect("failed to map memory for GenericAddressStructure")
.flush();
}
pub unsafe fn read_u64(&self, offset: usize) -> u64{
pub unsafe fn read_u64(&self, offset: usize) -> u64 {
read_volatile((crate::HPET_OFFSET + offset) as *const u64)
}
@@ -96,17 +104,27 @@ impl GenericAddressStructure {
let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
let (_, result) = mapper
.get_mut()
.expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
.map_linearly(frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.expect(
"KernelMapper locked re-entrant while mapping memory for GenericAddressStructure",
)
.map_linearly(
frame.start_address(),
PageFlags::new()
.write(true)
.custom_flag(EntryFlags::NO_CACHE.bits(), true),
)
.expect("failed to map memory for GenericAddressStructure");
result.flush();
}
pub unsafe fn read_u64(&self, offset: usize) -> u64{
pub unsafe fn read_u64(&self, offset: usize) -> u64 {
read_volatile((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64)
}
pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
write_volatile((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value);
write_volatile(
(self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64,
value,
);
}
}
+139 -110
View File
@@ -1,23 +1,26 @@
use core::mem;
use crate::memory::{allocate_frames, Frame};
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use crate::{
memory::{allocate_frames, Frame},
paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress},
};
use super::sdt::Sdt;
use super::find_sdt;
use super::{find_sdt, sdt::Sdt};
use core::sync::atomic::{AtomicU8, Ordering};
use crate::device::local_apic::LOCAL_APIC;
use crate::interrupt;
use crate::start::{kstart_ap, CPU_COUNT, AP_READY};
use crate::{
device::local_apic::LOCAL_APIC,
interrupt,
start::{kstart_ap, AP_READY, CPU_COUNT},
};
/// The Multiple APIC Descriptor Table
#[derive(Clone, Copy, Debug)]
pub struct Madt {
sdt: &'static Sdt,
pub local_address: u32,
pub flags: u32
pub flags: u32,
}
const TRAMPOLINE: usize = 0x8000;
@@ -80,85 +83,96 @@ impl Madt {
for madt_entry in madt.iter() {
println!(" {:?}", madt_entry);
match madt_entry {
MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me {
println!(" This is my local APIC");
} else {
if ap_local_apic.flags & 1 == 1 {
// Increase CPU ID
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
// Allocate a stack
let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().data() + crate::PHYS_OFFSET;
let stack_end = stack_start + 64 * 4096;
let ap_ready = (TRAMPOLINE + 8) as *mut u64;
let ap_cpu_id = unsafe { ap_ready.add(1) };
let ap_page_table = unsafe { ap_ready.add(2) };
let ap_stack_start = unsafe { ap_ready.add(3) };
let ap_stack_end = unsafe { ap_ready.add(4) };
let ap_code = unsafe { ap_ready.add(5) };
// Set the ap_ready to 0, volatile
unsafe {
ap_ready.write(0);
ap_cpu_id.write(ap_local_apic.id.into());
ap_page_table.write(page_table_physaddr as u64);
ap_stack_start.write(stack_start as u64);
ap_stack_end.write(stack_end as u64);
ap_code.write(kstart_ap as u64);
// TODO: Is this necessary (this fence)?
core::arch::asm!("");
};
AP_READY.store(false, Ordering::SeqCst);
print!(" AP {}:", ap_local_apic.id);
// Send INIT IPI
{
let mut icr = 0x4500;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" IPI...");
local_apic.set_icr(icr);
}
// Send START IPI
{
//Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
let ap_segment = (TRAMPOLINE >> 12) & 0xFF;
let mut icr = 0x4600 | ap_segment as u64;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" SIPI...");
local_apic.set_icr(icr);
}
// Wait for trampoline ready
print!(" Wait...");
while unsafe { (*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst) } == 0 {
interrupt::pause();
}
print!(" Trampoline...");
while ! AP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
println!(" Ready");
unsafe { RmmA::invalidate_all(); }
MadtEntry::LocalApic(ap_local_apic) => {
if ap_local_apic.id == me {
println!(" This is my local APIC");
} else {
println!(" CPU Disabled");
if ap_local_apic.flags & 1 == 1 {
// Increase CPU ID
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
// Allocate a stack
let stack_start = allocate_frames(64)
.expect("no more frames in acpi stack_start")
.start_address()
.data()
+ crate::PHYS_OFFSET;
let stack_end = stack_start + 64 * 4096;
let ap_ready = (TRAMPOLINE + 8) as *mut u64;
let ap_cpu_id = unsafe { ap_ready.add(1) };
let ap_page_table = unsafe { ap_ready.add(2) };
let ap_stack_start = unsafe { ap_ready.add(3) };
let ap_stack_end = unsafe { ap_ready.add(4) };
let ap_code = unsafe { ap_ready.add(5) };
// Set the ap_ready to 0, volatile
unsafe {
ap_ready.write(0);
ap_cpu_id.write(ap_local_apic.id.into());
ap_page_table.write(page_table_physaddr as u64);
ap_stack_start.write(stack_start as u64);
ap_stack_end.write(stack_end as u64);
ap_code.write(kstart_ap as u64);
// TODO: Is this necessary (this fence)?
core::arch::asm!("");
};
AP_READY.store(false, Ordering::SeqCst);
print!(" AP {}:", ap_local_apic.id);
// Send INIT IPI
{
let mut icr = 0x4500;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" IPI...");
local_apic.set_icr(icr);
}
// Send START IPI
{
//Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
let ap_segment = (TRAMPOLINE >> 12) & 0xFF;
let mut icr = 0x4600 | ap_segment as u64;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" SIPI...");
local_apic.set_icr(icr);
}
// Wait for trampoline ready
print!(" Wait...");
while unsafe {
(*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst)
} == 0
{
interrupt::pause();
}
print!(" Trampoline...");
while !AP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
println!(" Ready");
unsafe {
RmmA::invalidate_all();
}
} else {
println!(" CPU Disabled");
}
}
},
_ => ()
}
_ => (),
}
}
@@ -176,14 +190,15 @@ impl Madt {
}
pub fn new(sdt: &'static Sdt) -> Option<Madt> {
if &sdt.signature == b"APIC" && sdt.data_len() >= 8 { //Not valid if no local address and flags
if &sdt.signature == b"APIC" && sdt.data_len() >= 8 {
//Not valid if no local address and flags
let local_address = unsafe { *(sdt.data_address() as *const u32) };
let flags = unsafe { *(sdt.data_address() as *const u32).offset(1) };
Some(Madt {
sdt,
local_address,
flags
flags,
})
} else {
None
@@ -193,7 +208,7 @@ impl Madt {
pub fn iter(&self) -> MadtIter {
MadtIter {
sdt: self.sdt,
i: 8 // Skip local controller address and flags
i: 8, // Skip local controller address and flags
}
}
}
@@ -207,7 +222,7 @@ pub struct MadtLocalApic {
/// Local APIC ID
pub id: u8,
/// Flags. 1 means that the processor is enabled
pub flags: u32
pub flags: u32,
}
/// MADT I/O APIC
@@ -221,7 +236,7 @@ pub struct MadtIoApic {
/// I/O APIC address
pub address: u32,
/// Global system interrupt base
pub gsi_base: u32
pub gsi_base: u32,
}
/// MADT Interrupt Source Override
@@ -235,7 +250,7 @@ pub struct MadtIntSrcOverride {
/// Global system interrupt base
pub gsi_base: u32,
/// Flags
pub flags: u16
pub flags: u16,
}
/// MADT Entries
@@ -247,12 +262,12 @@ pub enum MadtEntry {
InvalidIoApic(usize),
IntSrcOverride(&'static MadtIntSrcOverride),
InvalidIntSrcOverride(usize),
Unknown(u8)
Unknown(u8),
}
pub struct MadtIter {
sdt: &'static Sdt,
i: usize
i: usize,
}
impl Iterator for MadtIter {
@@ -260,26 +275,40 @@ impl Iterator for MadtIter {
fn next(&mut self) -> Option<Self::Item> {
if self.i + 1 < self.sdt.data_len() {
let entry_type = unsafe { *(self.sdt.data_address() as *const u8).add(self.i) };
let entry_len = unsafe { *(self.sdt.data_address() as *const u8).add(self.i + 1) } as usize;
let entry_len =
unsafe { *(self.sdt.data_address() as *const u8).add(self.i + 1) } as usize;
if self.i + entry_len <= self.sdt.data_len() {
let item = match entry_type {
0 => if entry_len == mem::size_of::<MadtLocalApic>() + 2 {
MadtEntry::LocalApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic) })
} else {
MadtEntry::InvalidLocalApic(entry_len)
},
1 => if entry_len == mem::size_of::<MadtIoApic>() + 2 {
MadtEntry::IoApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic) })
} else {
MadtEntry::InvalidIoApic(entry_len)
},
2 => if entry_len == mem::size_of::<MadtIntSrcOverride>() + 2 {
MadtEntry::IntSrcOverride(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIntSrcOverride) })
} else {
MadtEntry::InvalidIntSrcOverride(entry_len)
},
_ => MadtEntry::Unknown(entry_type)
0 => {
if entry_len == mem::size_of::<MadtLocalApic>() + 2 {
MadtEntry::LocalApic(unsafe {
&*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic)
})
} else {
MadtEntry::InvalidLocalApic(entry_len)
}
}
1 => {
if entry_len == mem::size_of::<MadtIoApic>() + 2 {
MadtEntry::IoApic(unsafe {
&*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic)
})
} else {
MadtEntry::InvalidIoApic(entry_len)
}
}
2 => {
if entry_len == mem::size_of::<MadtIntSrcOverride>() + 2 {
MadtEntry::IntSrcOverride(unsafe {
&*((self.sdt.data_address() + self.i + 2)
as *const MadtIntSrcOverride)
})
} else {
MadtEntry::InvalidIntSrcOverride(entry_len)
}
}
_ => MadtEntry::Unknown(entry_type),
};
self.i += entry_len;
+22 -18
View File
@@ -1,38 +1,37 @@
//! # ACPI
//! Code to parse the ACPI tables
use alloc::string::String;
use alloc::vec::Vec;
use alloc::boxed::Box;
use alloc::{boxed::Box, string::String, vec::Vec};
use hashbrown::HashMap;
use spin::{Once, RwLock};
use crate::log::info;
use crate::paging::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch};
use crate::{
log::info,
paging::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch},
};
use self::madt::Madt;
use self::rsdt::Rsdt;
use self::sdt::Sdt;
use self::xsdt::Xsdt;
use self::hpet::Hpet;
use self::rxsdt::Rxsdt;
use self::rsdp::RSDP;
use self::{hpet::Hpet, madt::Madt, rsdp::RSDP, rsdt::Rsdt, rxsdt::Rxsdt, sdt::Sdt, xsdt::Xsdt};
pub mod hpet;
pub mod madt;
mod rsdp;
mod rsdt;
mod rxsdt;
pub mod sdt;
mod xsdt;
mod rxsdt;
mod rsdp;
unsafe fn map_linearly(addr: PhysicalAddress, len: usize, mapper: &mut crate::paging::PageMapper) {
let base = PhysicalAddress::new(crate::paging::round_down_pages(addr.data()));
let aligned_len = crate::paging::round_up_pages(len + (addr.data() - base.data()));
for page_idx in 0..aligned_len / crate::memory::PAGE_SIZE {
let (_, flush) = mapper.map_linearly(base.add(page_idx * crate::memory::PAGE_SIZE), PageFlags::new()).expect("failed to linearly map SDT");
let (_, flush) = mapper
.map_linearly(
base.add(page_idx * crate::memory::PAGE_SIZE),
PageFlags::new(),
)
.expect("failed to linearly map SDT");
flush.flush();
}
}
@@ -52,7 +51,11 @@ pub fn get_sdt(sdt_address: usize, mapper: &mut KernelMapper) -> &'static Sdt {
sdt = &*(RmmA::phys_to_virt(physaddr).data() as *const Sdt);
map_linearly(physaddr.add(SDT_SIZE), sdt.length as usize - SDT_SIZE, mapper);
map_linearly(
physaddr.add(SDT_SIZE),
sdt.length as usize - SDT_SIZE,
mapper,
);
}
sdt
}
@@ -151,7 +154,7 @@ pub type SdtSignature = (String, [u8; 6], [u8; 8]);
pub static SDT_POINTERS: RwLock<Option<HashMap<SdtSignature, &'static Sdt>>> = RwLock::new(None);
pub fn find_sdt(name: &str) -> Vec<&'static Sdt> {
let mut sdts: Vec<&'static Sdt> = vec!();
let mut sdts: Vec<&'static Sdt> = vec![];
if let Some(ref ptrs) = *(SDT_POINTERS.read()) {
for (signature, sdt) in ptrs {
@@ -165,7 +168,8 @@ pub fn find_sdt(name: &str) -> Vec<&'static Sdt> {
}
pub fn get_sdt_signature(sdt: &'static Sdt) -> SdtSignature {
let signature = String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string");
let signature =
String::from_utf8(sdt.signature.to_vec()).expect("Error converting signature to string");
(signature, sdt.oem_id, sdt.oem_table_id)
}
+41 -15
View File
@@ -1,8 +1,9 @@
use core::convert::TryFrom;
use core::mem;
use core::{convert::TryFrom, mem};
use crate::memory::Frame;
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress};
use crate::{
memory::Frame,
paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress},
};
/// RSDP
#[derive(Copy, Clone, Debug)]
@@ -16,7 +17,7 @@ pub struct RSDP {
_length: u32,
xsdt_address: u64,
_extended_checksum: u8,
_reserved: [u8; 3]
_reserved: [u8; 3],
}
impl RSDP {
@@ -36,12 +37,16 @@ impl RSDP {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.buf.len() < 4 { return None }
if self.buf.len() < 4 {
return None;
}
let length_bytes = <[u8; 4]>::try_from(&self.buf[..4]).ok()?;
let length = u32::from_ne_bytes(length_bytes) as usize;
if (4 + length as usize) > self.buf.len() { return None }
if (4 + length as usize) > self.buf.len() {
return None;
}
let buf = &self.buf[4..4 + length];
self.buf = &self.buf[4 + length..];
@@ -56,24 +61,36 @@ impl RSDP {
let rsdp = unsafe { &*(slice.as_ptr() as *const RSDP) };
// TODO: Validate
Some(rsdp)
} else { None }
} else {
None
}
}
// first, find an RSDP for ACPI 2.0
if let Some(rsdp_2_0) = (Iter { buf: area }.filter_map(slice_to_rsdp).find(|rsdp| rsdp.is_acpi_2_0())) {
if let Some(rsdp_2_0) = (Iter { buf: area }
.filter_map(slice_to_rsdp)
.find(|rsdp| rsdp.is_acpi_2_0()))
{
return Some(*rsdp_2_0);
}
// secondly, find an RSDP for ACPI 1.0
if let Some(rsdp_1_0) = (Iter { buf: area }.filter_map(slice_to_rsdp).find(|rsdp| rsdp.is_acpi_1_0())) {
if let Some(rsdp_1_0) = (Iter { buf: area }
.filter_map(slice_to_rsdp)
.find(|rsdp| rsdp.is_acpi_1_0()))
{
return Some(*rsdp_1_0);
}
None
}
pub fn get_rsdp(mapper: &mut KernelMapper, already_supplied_rsdps: Option<(u64, u64)>) -> Option<RSDP> {
pub fn get_rsdp(
mapper: &mut KernelMapper,
already_supplied_rsdps: Option<(u64, u64)>,
) -> Option<RSDP> {
if let Some((base, size)) = already_supplied_rsdps {
let area = unsafe { core::slice::from_raw_parts(base as usize as *const u8, size as usize) };
let area =
unsafe { core::slice::from_raw_parts(base as usize as *const u8, size as usize) };
Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(mapper))
} else {
Self::get_rsdp_by_searching(mapper)
@@ -89,9 +106,18 @@ impl RSDP {
let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr));
for frame in Frame::range_inclusive(start_frame, end_frame) {
let page = Page::containing_address(VirtualAddress::new(frame.start_address().data()));
let page =
Page::containing_address(VirtualAddress::new(frame.start_address().data()));
let result = unsafe {
mapper.get_mut().expect("KernelMapper locked re-entrant while locating RSDPs").map_phys(page.start_address(), frame.start_address(), PageFlags::new()).expect("failed to map page while searching for RSDP")
mapper
.get_mut()
.expect("KernelMapper locked re-entrant while locating RSDPs")
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new(),
)
.expect("failed to map page while searching for RSDP")
};
result.flush();
}
@@ -101,7 +127,7 @@ impl RSDP {
}
fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
for i in 0 .. (end_addr + 1 - start_addr)/16 {
for i in 0..(end_addr + 1 - start_addr) / 16 {
let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
if &rsdp.signature == b"RSD PTR " {
return Some(*rsdp);
+8 -15
View File
@@ -1,9 +1,7 @@
use core::convert::TryFrom;
use core::mem;
use alloc::boxed::Box;
use core::{convert::TryFrom, mem};
use super::sdt::Sdt;
use super::rxsdt::Rxsdt;
use super::{rxsdt::Rxsdt, sdt::Sdt};
#[derive(Debug)]
pub struct Rsdt(&'static Sdt);
@@ -17,33 +15,28 @@ impl Rsdt {
}
}
pub fn as_slice(&self) -> &[u8] {
let length = usize::try_from(self.0.length)
.expect("expected 32-bit length to fit within usize");
let length =
usize::try_from(self.0.length).expect("expected 32-bit length to fit within usize");
unsafe {
core::slice::from_raw_parts(self.0 as *const _ as *const u8, length)
}
unsafe { core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) }
}
}
impl Rxsdt for Rsdt {
fn iter(&self) -> Box<dyn Iterator<Item = usize>> {
Box::new(RsdtIter {
sdt: self.0,
i: 0
})
Box::new(RsdtIter { sdt: self.0, i: 0 })
}
}
pub struct RsdtIter {
sdt: &'static Sdt,
i: usize
i: usize,
}
impl Iterator for RsdtIter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.sdt.data_len()/mem::size_of::<u32>() {
if self.i < self.sdt.data_len() / mem::size_of::<u32>() {
let item = unsafe { *(self.sdt.data_address() as *const u32).add(self.i) };
self.i += 1;
Some(item as usize)
+7 -3
View File
@@ -2,8 +2,7 @@ use alloc::boxed::Box;
use crate::paging::KernelMapper;
use super::sdt::Sdt;
use super::get_sdt;
use super::{get_sdt, sdt::Sdt};
pub trait Rxsdt {
fn iter(&self) -> Box<dyn Iterator<Item = usize>>;
@@ -15,7 +14,12 @@ pub trait Rxsdt {
}
}
fn find(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> Option<&'static Sdt> {
fn find(
&self,
signature: [u8; 4],
oem_id: [u8; 6],
oem_table_id: [u8; 8],
) -> Option<&'static Sdt> {
for sdt in self.iter() {
let sdt = unsafe { &*(sdt as *const Sdt) };
+16 -12
View File
@@ -1,18 +1,17 @@
use core::mem;
use core::slice;
use core::{mem, slice};
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct Sdt {
pub signature: [u8; 4],
pub length: u32,
pub revision: u8,
pub checksum: u8,
pub oem_id: [u8; 6],
pub oem_table_id: [u8; 8],
pub oem_revision: u32,
pub creator_id: u32,
pub creator_revision: u32
pub signature: [u8; 4],
pub length: u32,
pub revision: u8,
pub checksum: u8,
pub oem_id: [u8; 6],
pub oem_table_id: [u8; 8],
pub oem_revision: u32,
pub creator_id: u32,
pub creator_revision: u32,
}
impl Sdt {
@@ -36,7 +35,12 @@ impl Sdt {
unsafe { slice::from_raw_parts(self.data_address() as *const u8, self.data_len()) }
}
pub fn match_pattern(&self, signature: [u8; 4], oem_id: [u8; 6], oem_table_id: [u8; 8]) -> bool{
pub fn match_pattern(
&self,
signature: [u8; 4],
oem_id: [u8; 6],
oem_table_id: [u8; 8],
) -> bool {
self.signature == signature && self.oem_id == oem_id && self.oem_table_id == oem_table_id
}
}
+8 -15
View File
@@ -1,9 +1,7 @@
use core::convert::TryFrom;
use core::mem;
use alloc::boxed::Box;
use core::{convert::TryFrom, mem};
use super::sdt::Sdt;
use super::rxsdt::Rxsdt;
use super::{rxsdt::Rxsdt, sdt::Sdt};
#[derive(Debug)]
pub struct Xsdt(&'static Sdt);
@@ -17,33 +15,28 @@ impl Xsdt {
}
}
pub fn as_slice(&self) -> &[u8] {
let length = usize::try_from(self.0.length)
.expect("expected 32-bit length to fit within usize");
let length =
usize::try_from(self.0.length).expect("expected 32-bit length to fit within usize");
unsafe {
core::slice::from_raw_parts(self.0 as *const _ as *const u8, length)
}
unsafe { core::slice::from_raw_parts(self.0 as *const _ as *const u8, length) }
}
}
impl Rxsdt for Xsdt {
fn iter(&self) -> Box<dyn Iterator<Item = usize>> {
Box::new(XsdtIter {
sdt: self.0,
i: 0
})
Box::new(XsdtIter { sdt: self.0, i: 0 })
}
}
pub struct XsdtIter {
sdt: &'static Sdt,
i: usize
i: usize,
}
impl Iterator for XsdtIter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.sdt.data_len()/mem::size_of::<u64>() {
if self.i < self.sdt.data_len() / mem::size_of::<u64>() {
let item = unsafe { *(self.sdt.data_address() as *const u64).add(self.i) };
self.i += 1;
Some(item as usize)
+15 -5
View File
@@ -1,5 +1,7 @@
use core::alloc::{GlobalAlloc, Layout};
use core::ptr::{self, NonNull};
use core::{
alloc::{GlobalAlloc, Layout},
ptr::{self, NonNull},
};
use linked_list_allocator::Heap;
use spin::Mutex;
@@ -21,10 +23,18 @@ unsafe impl GlobalAlloc for Allocator {
match heap.allocate_first_fit(layout) {
Err(()) => {
let size = heap.size();
super::map_heap(&mut KernelMapper::lock(), crate::KERNEL_HEAP_OFFSET + size, crate::KERNEL_HEAP_SIZE);
super::map_heap(
&mut KernelMapper::lock(),
crate::KERNEL_HEAP_OFFSET + size,
crate::KERNEL_HEAP_SIZE,
);
heap.extend(crate::KERNEL_HEAP_SIZE);
},
other => return other.ok().map_or(ptr::null_mut(), |allocation| allocation.as_ptr()),
}
other => {
return other
.ok()
.map_or(ptr::null_mut(), |allocation| allocation.as_ptr())
}
}
}
panic!("__rust_allocate: heap not initialized");
+16 -8
View File
@@ -1,26 +1,34 @@
use crate::paging::{mapper::PageFlushAll, KernelMapper, Page, PageFlags, VirtualAddress};
use rmm::Flusher;
use crate::paging::{KernelMapper, Page, PageFlags, VirtualAddress, mapper::PageFlushAll};
#[cfg(not(feature="slab"))]
#[cfg(not(feature = "slab"))]
pub use self::linked_list::Allocator;
#[cfg(feature="slab")]
#[cfg(feature = "slab")]
pub use self::slab::Allocator;
#[cfg(not(feature="slab"))]
#[cfg(not(feature = "slab"))]
mod linked_list;
#[cfg(feature="slab")]
#[cfg(feature = "slab")]
mod slab;
unsafe fn map_heap(mapper: &mut KernelMapper, offset: usize, size: usize) {
let mapper = mapper.get_mut().expect("failed to obtain exclusive access to KernelMapper while extending heap");
let mapper = mapper
.get_mut()
.expect("failed to obtain exclusive access to KernelMapper while extending heap");
let mut flush_all = PageFlushAll::new();
let heap_start_page = Page::containing_address(VirtualAddress::new(offset));
let heap_end_page = Page::containing_address(VirtualAddress::new(offset + size-1));
let heap_end_page = Page::containing_address(VirtualAddress::new(offset + size - 1));
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
let result = mapper.map(page.start_address(), PageFlags::new().write(true).global(cfg!(not(feature = "pti"))))
let result = mapper
.map(
page.start_address(),
PageFlags::new()
.write(true)
.global(cfg!(not(feature = "pti"))),
)
.expect("failed to map kernel heap");
flush_all.consume(result);
}
+1 -1
View File
@@ -1,6 +1,6 @@
use core::alloc::{Alloc, AllocErr, Layout};
use spin::Mutex;
use slab_allocator::Heap;
use spin::Mutex;
static HEAP: Mutex<Option<Heap>> = Mutex::new(None);
+5 -5
View File
@@ -8,15 +8,15 @@ pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;
/// Offset of recursive paging (deprecated, but still reserved)
pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize;
pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK)/PML4_SIZE;
pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK) / PML4_SIZE;
/// Offset of kernel
pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE;
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK) / PML4_SIZE;
/// Offset to kernel heap
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK) / PML4_SIZE;
/// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
@@ -25,7 +25,7 @@ pub const KERNEL_TMP_MISC_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
/// Offset to kernel percpu variables
pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_TMP_MISC_OFFSET - PML4_SIZE;
pub const KERNEL_PERCPU_PML4: usize = (KERNEL_PERCPU_OFFSET & PML4_MASK)/PML4_SIZE;
pub const KERNEL_PERCPU_PML4: usize = (KERNEL_PERCPU_OFFSET & PML4_MASK) / PML4_SIZE;
/// Size of kernel percpu variables
pub const KERNEL_PERCPU_SHIFT: u8 = 16; // 2^16 = 64 KiB
pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
@@ -33,7 +33,7 @@ pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
/// Offset of physmap
// This needs to match RMM's PHYS_OFFSET
pub const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK) / PML4_SIZE;
/// End offset of the user image, i.e. kernel start
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
+4 -7
View File
@@ -1,15 +1,12 @@
use core::fmt;
use spin::MutexGuard;
use crate::log::{LOG, Log};
use crate::log::{Log, LOG};
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
#[cfg(feature = "serial_debug")]
use super::device::{
serial::COM1,
uart_pl011::SerialPort,
};
use super::device::{serial::COM1, uart_pl011::SerialPort};
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DebugDisplay, DEBUG_DISPLAY};
pub struct Writer<'a> {
log: MutexGuard<'a, Option<Log>>,
+8 -33
View File
@@ -1,6 +1,6 @@
use core::fmt::{Result, Write};
use crate::device::cpu::registers::{control_regs};
use crate::device::cpu::registers::control_regs;
pub mod registers;
@@ -29,28 +29,15 @@ enum ImplementerID {
}
const IMPLEMENTERS: [&'static str; 12] = [
"Unknown",
"Arm",
"Broadcom",
"Cavium",
"Digital",
"Infineon",
"Motorola",
"Nvidia",
"AMCC",
"Qualcomm",
"Marvell",
"Intel",
"Unknown", "Arm", "Broadcom", "Cavium", "Digital", "Infineon", "Motorola", "Nvidia", "AMCC",
"Qualcomm", "Marvell", "Intel",
];
enum VariantID {
Unknown,
}
const VARIANTS: [&'static str; 1] = [
"Unknown",
];
const VARIANTS: [&'static str; 1] = ["Unknown"];
enum ArchitectureID {
Unknown,
@@ -63,16 +50,8 @@ enum ArchitectureID {
V6,
}
const ARCHITECTURES: [&'static str; 8] = [
"Unknown",
"v4",
"v4T",
"v5",
"v5T",
"v5TE",
"v5TEJ",
"v6",
];
const ARCHITECTURES: [&'static str; 8] =
["Unknown", "v4", "v4T", "v5", "v5T", "v5TE", "v5TEJ", "v6"];
enum PartNumberID {
Unknown,
@@ -106,11 +85,7 @@ enum RevisionID {
Thunder1_1,
}
const REVISIONS: [&'static str; 3] = [
"Unknown",
"Thunder-1.0",
"Thunder-1.1",
];
const REVISIONS: [&'static str; 3] = ["Unknown", "Thunder-1.0", "Thunder-1.1"];
struct CpuInfo {
implementer: &'static str,
@@ -177,7 +152,7 @@ impl CpuInfo {
_ => REVISIONS[RevisionID::Unknown as usize],
};
val
},
}
_ => REVISIONS[RevisionID::Unknown as usize],
};
+26 -17
View File
@@ -1,19 +1,15 @@
use crate::log::{debug, info};
use alloc::boxed::Box;
use crate::log::{info, debug};
use crate::{
arch::device::irqchip::IRQ_CHIP, context, context::timeout,
device::cpu::registers::control_regs, dtb::DTB_BINARY, init::device_tree::find_compatible_node,
interrupt::irq::trigger, time,
};
use alloc::vec::Vec;
use byteorder::{ByteOrder, BE};
use crate::arch::device::irqchip::IRQ_CHIP;
use crate::context::timeout;
use crate::device::cpu::registers::control_regs;
use crate::init::device_tree::find_compatible_node;
use crate::interrupt::irq::trigger;
use crate::time;
use crate::context;
use crate::dtb::DTB_BINARY;
use super::irqchip::InterruptHandler;
use super::irqchip::register_irq;
use super::irqchip::{register_irq, InterruptHandler};
bitflags! {
struct TimerCtrlFlags: u32 {
@@ -24,19 +20,28 @@ bitflags! {
}
pub unsafe fn init() {
let mut timer = GenericTimer{ clk_freq: 0, reload_count: 0};
let mut timer = GenericTimer {
clk_freq: 0,
reload_count: 0,
};
timer.init();
let data = DTB_BINARY.get().unwrap();
let fdt = fdt::DeviceTree::new(data).unwrap();
if let Some(node) = find_compatible_node(&fdt, "arm,armv7-timer") {
let interrupts = node.properties().find(|p| p.name.contains("interrupts")).unwrap();
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
let val = BE::read_u32(chunk);
intr_data.push(val);
}
let mut ic_idx = IRQ_CHIP.irq_chip_list.root_idx;
if let Some(interrupt_parent) = node.properties().find(|p| p.name.contains("interrupt-parent")) {
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
let mut i = 0;
while i < IRQ_CHIP.irq_chip_list.chips.len() {
@@ -49,7 +54,10 @@ pub unsafe fn init() {
}
}
//PHYS_NONSECURE_PPI only
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx].ic.irq_xlate(&intr_data, 1).unwrap();
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx]
.ic
.irq_xlate(&intr_data, 1)
.unwrap();
info!("generic_timer virq = {}", virq);
register_irq(virq as u32, Box::new(timer));
IRQ_CHIP.irq_enable(virq as u32);
@@ -109,7 +117,6 @@ impl GenericTimer {
impl InterruptHandler for GenericTimer {
fn irq_handler(&mut self, irq: u32) {
self.clear_irq();
{
*time::OFFSET.lock() += self.clk_freq as u128;
@@ -119,7 +126,9 @@ impl InterruptHandler for GenericTimer {
context::switch::tick();
unsafe { trigger(irq); }
unsafe {
trigger(irq);
}
self.reload_count();
}
}
+37 -18
View File
@@ -1,11 +1,16 @@
use core::ptr::{read_volatile, write_volatile};
use fdt::{DeviceTree, Node};
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use crate::init::device_tree::find_compatible_node;
use crate::log::{info, debug};
use syscall::{Result, error::{Error, EINVAL}};
use crate::{
init::device_tree::find_compatible_node,
log::{debug, info},
};
use syscall::{
error::{Error, EINVAL},
Result,
};
use super::{InterruptController, IrqDesc};
@@ -35,11 +40,13 @@ impl GenericInterruptController {
ncpus: 0,
nirqs: 0,
};
let gic_cpu_if = GicCpuIf {
address: 0,
};
let gic_cpu_if = GicCpuIf { address: 0 };
GenericInterruptController { gic_dist_if, gic_cpu_if, irq_range: (0, 0) }
GenericInterruptController {
gic_dist_if,
gic_cpu_if,
irq_range: (0, 0),
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize, usize, usize)> {
if let Some(node) = find_compatible_node(fdt, "arm,cortex-a15-gic") {
@@ -76,11 +83,18 @@ impl GenericInterruptController {
}
impl InterruptController for GenericInterruptController {
fn irq_init(&mut self, fdt: &DeviceTree, irq_desc: &mut [IrqDesc; 1024], ic_idx: usize, irq_idx: &mut usize) -> Result<Option<usize>> {
let (dist_addr, dist_size, cpu_addr, cpu_size) = match GenericInterruptController::parse(fdt) {
Ok(regs) => regs,
Err(err) => return Err(err),
};
fn irq_init(
&mut self,
fdt: &DeviceTree,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
) -> Result<Option<usize>> {
let (dist_addr, dist_size, cpu_addr, cpu_size) =
match GenericInterruptController::parse(fdt) {
Ok(regs) => regs,
Err(err) => return Err(err),
};
unsafe {
self.gic_cpu_if.init(crate::PHYS_OFFSET + cpu_addr);
@@ -92,7 +106,11 @@ impl InterruptController for GenericInterruptController {
self.gic_cpu_if.write(GICC_PMR, 0xff);
}
let idx = *irq_idx;
let cnt = if self.gic_dist_if.nirqs > 1024 { 1024 } else { self.gic_dist_if.nirqs as usize };
let cnt = if self.gic_dist_if.nirqs > 1024 {
1024
} else {
self.gic_dist_if.nirqs as usize
};
let mut i: usize = 0;
//only support linear irq map now.
while i < cnt && (idx + i < 1024) {
@@ -145,9 +163,7 @@ impl InterruptController for GenericInterruptController {
}
}
fn irq_handler(&mut self, _irq: u32) {
}
fn irq_handler(&mut self, _irq: u32) {}
}
pub struct GicDistIf {
@@ -166,7 +182,10 @@ impl GicDistIf {
let typer = self.read(GICD_TYPER);
self.ncpus = ((typer & (0x7 << 5)) >> 5) + 1;
self.nirqs = ((typer & 0x1f) + 1) * 32;
info!("gic: Distributor supports {:?} CPUs and {:?} IRQs", self.ncpus, self.nirqs);
info!(
"gic: Distributor supports {:?} CPUs and {:?} IRQs",
self.ncpus, self.nirqs
);
// Set all SPIs to level triggered
for irq in (32..self.nirqs).step_by(16) {
+85 -47
View File
@@ -1,16 +1,20 @@
use alloc::{boxed::Box, vec::Vec};
use core::ptr::{read_volatile, write_volatile};
use alloc::boxed::Box;
use alloc::vec::Vec;
use crate::arch::device::irqchip::IRQ_CHIP;
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use crate::arch::device::irqchip::IRQ_CHIP;
use crate::init::device_tree::find_compatible_node;
use crate::log::{info, debug, error};
use syscall::{Result, error::{Error, EINVAL}};
use crate::{
init::device_tree::find_compatible_node,
log::{debug, error, info},
};
use syscall::{
error::{Error, EINVAL},
Result,
};
use super::{InterruptController, IrqDesc, InterruptHandler};
use super::{InterruptController, InterruptHandler, IrqDesc};
#[inline(always)]
fn ffs(num: u32) -> u32 {
@@ -39,7 +43,7 @@ fn ffs(num: u32) -> u32 {
x >>= 1;
r += 1;
}
r
}
@@ -59,10 +63,12 @@ pub struct Bcm2835ArmInterruptController {
pub irq_range: (usize, usize),
}
impl Bcm2835ArmInterruptController {
pub fn new() -> Self {
Bcm2835ArmInterruptController { address: 0, irq_range: (0, 0) }
Bcm2835ArmInterruptController {
address: 0,
irq_range: (0, 0),
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize, Option<usize>)> {
//TODO: try to parse dtb using stable library
@@ -79,10 +85,16 @@ impl Bcm2835ArmInterruptController {
let base = BE::read_u32(base);
let size = BE::read_u32(size);
let mut ret_virq = None;
if let Some(interrupt_parent) = node.properties().find(|p| p.name.contains("interrupt-parent")) {
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
let interrupts = node.properties().find(|p| p.name.contains("interrupts")).unwrap();
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
let val = BE::read_u32(chunk);
@@ -99,7 +111,10 @@ impl Bcm2835ArmInterruptController {
i += 1;
}
//PHYS_NONSECURE_PPI only
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx].ic.irq_xlate(&intr_data, 0).unwrap();
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx]
.ic
.irq_xlate(&intr_data, 0)
.unwrap();
info!("bcm2835arm_ctrl virq = {}", virq);
ret_virq = Some(virq);
}
@@ -127,7 +142,13 @@ impl Bcm2835ArmInterruptController {
}
impl InterruptController for Bcm2835ArmInterruptController {
fn irq_init(&mut self, fdt: &DeviceTree, irq_desc: &mut [IrqDesc; 1024], ic_idx: usize, irq_idx: &mut usize) -> Result<Option<usize>> {
fn irq_init(
&mut self,
fdt: &DeviceTree,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
) -> Result<Option<usize>> {
let (base, size, virq) = match Bcm2835ArmInterruptController::parse(fdt) {
Ok((a, b, c)) => (a, b, c),
Err(_) => return Err(Error::new(EINVAL)),
@@ -161,8 +182,17 @@ impl InterruptController for Bcm2835ArmInterruptController {
let sources = unsafe { self.read(PENDING_0) };
let pending_num = ffs(sources) - 1;
let fast_irq = [
7 + 32, 9 + 32, 10 + 32, 18 + 32, 19 + 32,
21 + 64, 22 + 64, 23 + 64, 24 + 64, 25 + 64, 30 + 64
7 + 32,
9 + 32,
10 + 32,
18 + 32,
19 + 32,
21 + 64,
22 + 64,
23 + 64,
24 + 64,
25 + 64,
30 + 64,
];
//fast irq
@@ -172,66 +202,76 @@ impl InterruptController for Bcm2835ArmInterruptController {
let pending_num = ffs(sources & 0x3ff) - 1;
match pending_num {
num@0..=7 => {
return num
},
num @ 0..=7 => return num,
8 => {
let sources1 = unsafe { self.read(PENDING_1) };
let irq_0_31 = ffs(sources1) - 1;
return irq_0_31 + 32;
},
}
9 => {
let sources2 = unsafe { self.read(PENDING_2) };
let irq_32_63 = ffs(sources2) - 1;
return irq_32_63 + 64;
},
}
num => {
error!("unexpected irq pending in BASIC PENDING: 0x{}, sources = 0x{:08x}", num, sources);
error!(
"unexpected irq pending in BASIC PENDING: 0x{}, sources = 0x{:08x}",
num, sources
);
return num;
}
}
}
fn irq_eoi(&mut self, _irq_num: u32) {
}
fn irq_eoi(&mut self, _irq_num: u32) {}
fn irq_enable(&mut self, irq_num: u32) {
debug!("bcm2835 enable {} {}", irq_num, irq_num & 0x1f);
match irq_num {
num @0..=31 => {
num @ 0..=31 => {
let val = 1 << num;
unsafe { self.write(ENABLE_0, val); }
},
num @32..=63 => {
unsafe {
self.write(ENABLE_0, val);
}
}
num @ 32..=63 => {
let val = 1 << (num & 0x1f);
unsafe { self.write(ENABLE_1, val); }
},
num @64..=95 => {
unsafe {
self.write(ENABLE_1, val);
}
}
num @ 64..=95 => {
let val = 1 << (num & 0x1f);
unsafe { self.write(ENABLE_2, val); }
},
unsafe {
self.write(ENABLE_2, val);
}
}
_ => return,
}
}
fn irq_disable(&mut self, irq_num: u32) {
match irq_num {
num @0..=31 => {
num @ 0..=31 => {
let val = 1 << num;
unsafe { self.write(DISABLE_0, val); }
},
num @32..=63 => {
unsafe {
self.write(DISABLE_0, val);
}
}
num @ 32..=63 => {
let val = 1 << (num & 0x1f);
unsafe { self.write(DISABLE_1, val); }
},
num @64..=95 => {
unsafe {
self.write(DISABLE_1, val);
}
}
num @ 64..=95 => {
let val = 1 << (num & 0x1f);
unsafe { self.write(DISABLE_2, val); }
},
unsafe {
self.write(DISABLE_2, val);
}
}
_ => return,
}
}
fn irq_xlate(&mut self, irq_data: &[u32], idx: usize) -> Result<usize> {
//assert interrupt-cells == 0x2
@@ -260,7 +300,6 @@ impl InterruptController for Bcm2835ArmInterruptController {
}
fn irq_handler(&mut self, _irq: u32) {
unsafe {
let irq = self.irq_ack();
if let Some(virq) = self.irq_to_virq(irq) && virq < 1024 {
@@ -277,7 +316,6 @@ impl InterruptController for Bcm2835ArmInterruptController {
impl InterruptHandler for Bcm2835ArmInterruptController {
fn irq_handler(&mut self, _irq: u32) {
unsafe {
let irq = self.irq_ack();
if let Some(virq) = self.irq_to_virq(irq) && virq < 1024 {
+36 -19
View File
@@ -1,11 +1,19 @@
use core::{ptr::{read_volatile, write_volatile}, arch::asm};
use core::{
arch::asm,
ptr::{read_volatile, write_volatile},
};
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use crate::init::device_tree::find_compatible_node;
use crate::log::{info, debug};
use syscall::{Result, error::{Error, EINVAL}};
use crate::{
init::device_tree::find_compatible_node,
log::{debug, info},
};
use syscall::{
error::{Error, EINVAL},
Result,
};
use super::{InterruptController, IrqDesc};
@@ -55,7 +63,7 @@ fn ffs(num: u32) -> u32 {
x >>= 1;
r += 1;
}
r
}
@@ -65,10 +73,13 @@ pub struct Bcm2836ArmInterruptController {
pub active_cpu: u32,
}
impl Bcm2836ArmInterruptController {
pub fn new() -> Self {
Bcm2836ArmInterruptController { address: 0, irq_range: (0, 0), active_cpu: 0 }
Bcm2836ArmInterruptController {
address: 0,
irq_range: (0, 0),
active_cpu: 0,
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize)> {
//TODO: try to parse dtb using stable library
@@ -84,7 +95,7 @@ impl Bcm2836ArmInterruptController {
let (base, size) = reg.data.split_at(4);
let base = BE::read_u32(base);
let size = BE::read_u32(size);
Ok((base as usize, size as usize))
}
@@ -111,7 +122,13 @@ impl Bcm2836ArmInterruptController {
}
impl InterruptController for Bcm2836ArmInterruptController {
fn irq_init(&mut self, fdt: &DeviceTree, irq_desc: &mut [IrqDesc; 1024], ic_idx: usize, irq_idx: &mut usize) -> Result<Option<usize>> {
fn irq_init(
&mut self,
fdt: &DeviceTree,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
) -> Result<Option<usize>> {
let (base, size) = match Bcm2836ArmInterruptController::parse(fdt) {
Ok((a, b)) => (a, b),
Err(_) => return Err(Error::new(EINVAL)),
@@ -145,15 +162,15 @@ impl InterruptController for Bcm2836ArmInterruptController {
fn irq_ack(&mut self) -> u32 {
let mut cpuid: usize = 0;
unsafe { asm!("mrs {}, mpidr_el1", out(reg) cpuid); }
unsafe {
asm!("mrs {}, mpidr_el1", out(reg) cpuid);
}
let cpu = cpuid as u32 & 0x3;
let sources: u32 = unsafe { self.read(LOCAL_IRQ_PENDING + 4 * cpu) };
ffs(sources) - 1
}
fn irq_eoi(&mut self, _irq_num: u32) {
}
fn irq_eoi(&mut self, _irq_num: u32) {}
fn irq_enable(&mut self, irq_num: u32) {
match irq_num {
@@ -167,7 +184,7 @@ impl InterruptController for Bcm2836ArmInterruptController {
},
LOCAL_IRQ_GPU_FAST => {
//GPU IRQ always enable
},
}
_ => {
//ignore
}
@@ -178,7 +195,9 @@ impl InterruptController for Bcm2836ArmInterruptController {
match irq_num {
LOCAL_IRQ_CNTPNSIRQ => unsafe {
let mut cpuid: usize = 0;
unsafe { asm!("mrs {}, mpidr_el1", out(reg) cpuid); }
unsafe {
asm!("mrs {}, mpidr_el1", out(reg) cpuid);
}
let mut cpu = cpuid as u32 & 0x3;
let mut reg_val = self.read(LOCAL_TIMER_INT_CONTROL0 + 4 * cpu);
reg_val &= !0x2;
@@ -186,7 +205,7 @@ impl InterruptController for Bcm2836ArmInterruptController {
},
LOCAL_IRQ_GPU_FAST => {
//GPU IRQ always enable
},
}
_ => {
//ignore
}
@@ -213,7 +232,5 @@ impl InterruptController for Bcm2836ArmInterruptController {
}
}
fn irq_handler(&mut self, irq: u32) {
}
fn irq_handler(&mut self, irq: u32) {}
}
+65 -29
View File
@@ -1,10 +1,16 @@
use alloc::{boxed::Box, vec::Vec, string::{String, ToString}};
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use byteorder::{ByteOrder, BE};
use syscall::Result;
use fdt::DeviceTree;
use syscall::Result;
use crate::log::{debug, error};
use crate::init::device_tree::travel_interrupt_ctrl;
use crate::{
init::device_tree::travel_interrupt_ctrl,
log::{debug, error},
};
mod gic;
mod irq_bcm2835;
@@ -18,7 +24,13 @@ pub const IRQ_TYPE_LEVEL_HIGH: u32 = 4;
pub const IRQ_TYPE_LEVEL_LOW: u32 = 8;
pub trait InterruptController {
fn irq_init(&mut self, fdt: &DeviceTree, irq_desc: &mut [IrqDesc; 1024], ic_idx: usize, irq_idx: &mut usize) -> Result<Option<usize>>;
fn irq_init(
&mut self,
fdt: &DeviceTree,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
) -> Result<Option<usize>>;
fn irq_ack(&mut self) -> u32;
fn irq_eoi(&mut self, irq_num: u32);
fn irq_enable(&mut self, irq_num: u32);
@@ -38,7 +50,7 @@ pub struct IrqChipItem {
pub parent_phandle: Option<u32>,
pub intr_cell_size: u32,
pub parent: Option<usize>, //parent idx in chiplist
pub childs: Vec<usize>, //child idx in chiplist
pub childs: Vec<usize>, //child idx in chiplist
pub interrupts: Vec<u32>,
pub ic: Box<dyn InterruptController>,
}
@@ -51,10 +63,10 @@ pub struct IrqChipList {
pub struct IrqDescItem {
pub idx: usize,
pub ic_idx: usize, //ic idx in irq chip list
pub ic_idx: usize, //ic idx in irq chip list
pub child_ic_idx: Option<usize>, //ic idx in irq chip list
pub ic_irq: u32, //hwirq in ic
pub used: bool,
pub ic_irq: u32, //hwirq in ic
pub used: bool,
}
pub struct IrqDesc {
@@ -66,27 +78,50 @@ impl IrqChipList {
fn init_inner1(&mut self, fdt: &fdt::DeviceTree) {
let root_node = fdt.nodes().nth(0).unwrap();
let mut idx = 0;
let intr = root_node.properties().find(|p| p.name.contains("interrupt-parent")).unwrap();
let intr = root_node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
.unwrap();
let root_intr_parent = BE::read_u32(&intr.data);
debug!("root parent = 0x{:08x}", root_intr_parent);
self.root_phandle = root_intr_parent;
for node in fdt.nodes() {
if node.properties().find(|p| p.name.contains("interrupt-controller")).is_some() {
let compatible = node.properties().find(|p| p.name.contains("compatible")).unwrap();
let phandle = node.properties().find(|p| p.name.contains("phandle")).unwrap();
let intr_cells = node.properties().find(|p| p.name.contains("#interrupt-cells")).unwrap();
let _intr = node.properties().find(|p| p.name.contains("interrupt-parent"));
if node
.properties()
.find(|p| p.name.contains("interrupt-controller"))
.is_some()
{
let compatible = node
.properties()
.find(|p| p.name.contains("compatible"))
.unwrap();
let phandle = node
.properties()
.find(|p| p.name.contains("phandle"))
.unwrap();
let intr_cells = node
.properties()
.find(|p| p.name.contains("#interrupt-cells"))
.unwrap();
let _intr = node
.properties()
.find(|p| p.name.contains("interrupt-parent"));
let _intr_data = node.properties().find(|p| p.name.contains("interrupts"));
let s = core::str::from_utf8(compatible.data).unwrap();
debug!("{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}", node.name, s, BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data));
debug!(
"{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}",
node.name,
s,
BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data)
);
let mut item = IrqChipItem {
compatible: s.to_string(),
phandle: BE::read_u32(phandle.data),
parent_phandle: None,
intr_cell_size: BE::read_u32(intr_cells.data),
intr_cell_size: BE::read_u32(intr_cells.data),
parent: None,
childs: Vec::new(),
interrupts: Vec::new(),
@@ -111,7 +146,6 @@ impl IrqChipList {
self.chips.push(item);
idx += 1;
}
}
}
@@ -135,7 +169,6 @@ impl IrqChipList {
}
x += 1;
}
}
fn init_inner3(&mut self, fdt: &fdt::DeviceTree, irq_desc: &mut [IrqDesc; 1024]) {
@@ -146,13 +179,14 @@ impl IrqChipList {
while !queue.is_empty() {
let cur_idx = queue.pop().unwrap();
queue.extend_from_slice(&self.chips[cur_idx].childs);
let virq = self.chips[cur_idx].ic.irq_init(fdt, irq_desc, cur_idx, &mut irq_idx);
let virq = self.chips[cur_idx]
.ic
.irq_init(fdt, irq_desc, cur_idx, &mut irq_idx);
if let Ok(Some(virq)) = virq {
irq_desc[virq].basic.child_ic_idx = Some(cur_idx);
}
}
}
}
pub struct IrqChipCore {
@@ -164,7 +198,9 @@ pub struct IrqChipCore {
impl IrqChipCore {
pub fn irq_ack(&mut self) -> u32 {
self.irq_chip_list.chips[self.irq_chip_list.root_idx].ic.irq_ack()
self.irq_chip_list.chips[self.irq_chip_list.root_idx]
.ic
.irq_ack()
}
pub fn irq_eoi(&mut self, virq: u32) {
@@ -192,7 +228,9 @@ impl IrqChipCore {
}
pub fn irq_to_virq(&mut self, hwirq: u32) -> Option<usize> {
self.irq_chip_list.chips[self.irq_chip_list.root_idx].ic.irq_to_virq(hwirq)
self.irq_chip_list.chips[self.irq_chip_list.root_idx]
.ic
.irq_to_virq(hwirq)
}
pub fn init(&mut self, fdt: &DeviceTree) {
@@ -202,7 +240,6 @@ impl IrqChipCore {
self.irq_chip_list.init_inner1(fdt);
self.irq_chip_list.init_inner2();
self.irq_chip_list.init_inner3(fdt, &mut self.irq_desc);
}
pub fn new_ic(ic_str: &str) -> Option<Box<dyn InterruptController>> {
@@ -229,7 +266,7 @@ const INIT_IRQ_DESC: IrqDesc = IrqDesc {
},
handler: INIT_HANDLER,
};
pub static mut IRQ_CHIP: IrqChipCore = IrqChipCore {
pub static mut IRQ_CHIP: IrqChipCore = IrqChipCore {
irq_chip_list: IrqChipList {
chips: Vec::new(),
root_phandle: 0,
@@ -239,7 +276,6 @@ pub static mut IRQ_CHIP: IrqChipCore = IrqChipCore {
irq_desc: [INIT_IRQ_DESC; 1024],
};
pub fn init(fdt: &DeviceTree) {
travel_interrupt_ctrl(fdt);
unsafe {
@@ -250,13 +286,13 @@ pub fn init(fdt: &DeviceTree) {
pub fn register_irq(virq: u32, handler: Box<dyn InterruptHandler>) {
if virq >= 1024 {
error!("irq {} exceed 1024!!!", virq);
return ;
return;
}
unsafe {
if IRQ_CHIP.irq_desc[virq as usize].handler.is_some() {
error!("irq {} has already been registered!", virq);
return ;
return;
}
IRQ_CHIP.irq_desc[virq as usize].handler = Some(handler);
+17 -11
View File
@@ -1,15 +1,17 @@
use core::arch::asm;
use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, Page, PageFlags, VirtualAddress};
use crate::dtb::DTB_BINARY;
use crate::log::info;
use crate::{
dtb::DTB_BINARY,
log::info,
memory::Frame,
paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress},
};
pub mod cpu;
pub mod irqchip;
pub mod generic_timer;
pub mod serial;
pub mod irqchip;
pub mod rtc;
pub mod serial;
pub mod uart_pl011;
pub unsafe fn init() {
@@ -28,8 +30,7 @@ pub unsafe fn init_noncore() {
rtc::init();
}
pub unsafe fn init_ap() {
}
pub unsafe fn init_ap() {}
//map physical addr X to virtual addr PHYS_OFFSET + X
pub unsafe fn io_mmap(addr: usize, io_size: usize) {
@@ -38,13 +39,18 @@ pub unsafe fn io_mmap(addr: usize, io_size: usize) {
let start_frame = Frame::containing_address(PhysicalAddress::new(addr));
let end_frame = Frame::containing_address(PhysicalAddress::new(addr + io_size - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::PHYS_OFFSET));
let page = Page::containing_address(VirtualAddress::new(
frame.start_address().data() + crate::PHYS_OFFSET,
));
mapper
.get_mut()
.expect("failed to access KernelMapper for mapping GIC distributor")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true))
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new().write(true),
)
.expect("failed to map GIC distributor")
.flush();
}
}
+14 -8
View File
@@ -1,8 +1,10 @@
use core::ptr::{read_volatile, write_volatile};
use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, Page, PageFlags, TableKind, VirtualAddress};
use crate::time;
use crate::{
memory::Frame,
paging::{KernelMapper, Page, PageFlags, PhysicalAddress, TableKind, VirtualAddress},
time,
};
static RTC_DR: u32 = 0x000;
static RTC_MR: u32 = 0x004;
@@ -13,9 +15,7 @@ static RTC_RIS: u32 = 0x014;
static RTC_MIS: u32 = 0x018;
static RTC_ICR: u32 = 0x01c;
static mut PL031_RTC: Pl031rtc = Pl031rtc {
address: 0,
};
static mut PL031_RTC: Pl031rtc = Pl031rtc { address: 0 };
pub unsafe fn init() {
PL031_RTC.init();
@@ -34,11 +34,17 @@ impl Pl031rtc {
let end_frame = Frame::containing_address(PhysicalAddress::new(0x09010000 + 0x1000 - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::PHYS_OFFSET));
let page = Page::containing_address(VirtualAddress::new(
frame.start_address().data() + crate::PHYS_OFFSET,
));
mapper
.get_mut()
.expect("failed to access KernelMapper for mapping RTC")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true))
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new().write(true),
)
.expect("failed to map RTC")
.flush();
}
+25 -14
View File
@@ -1,31 +1,33 @@
use alloc::boxed::Box;
use spin::Mutex;
use crate::{device::uart_pl011::SerialPort, interrupt::irq::trigger};
use crate::init::device_tree;
use crate::log::{info, debug};
use crate::{
device::uart_pl011::SerialPort,
init::device_tree,
interrupt::irq::trigger,
log::{debug, info},
};
use super::irqchip::{register_irq, IRQ_CHIP, InterruptHandler};
use crate::dtb::DTB_BINARY;
use byteorder::{ByteOrder, BE};
use crate::init::device_tree::find_compatible_node;
use super::irqchip::{register_irq, InterruptHandler, IRQ_CHIP};
use crate::{dtb::DTB_BINARY, init::device_tree::find_compatible_node};
use alloc::vec::Vec;
use byteorder::{ByteOrder, BE};
pub static COM1: Mutex<Option<SerialPort>> = Mutex::new(None);
pub struct Com1Irq {
}
pub struct Com1Irq {}
impl InterruptHandler for Com1Irq {
fn irq_handler(&mut self, irq: u32) {
if let Some(ref mut serial_port) = *COM1.lock() {
serial_port.receive();
};
unsafe { trigger(irq); }
unsafe {
trigger(irq);
}
}
}
pub unsafe fn init_early(dtb_base: usize, dtb_size: usize) {
if COM1.lock().is_some() {
// Hardcoded UART
@@ -47,14 +49,20 @@ pub unsafe fn init() {
let data = DTB_BINARY.get().unwrap();
let fdt = fdt::DeviceTree::new(data).unwrap();
if let Some(node) = find_compatible_node(&fdt, "arm,pl011") {
let interrupts = node.properties().find(|p| p.name.contains("interrupts")).unwrap();
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
let val = BE::read_u32(chunk);
intr_data.push(val);
}
let mut ic_idx = IRQ_CHIP.irq_chip_list.root_idx;
if let Some(interrupt_parent) = node.properties().find(|p| p.name.contains("interrupt-parent")) {
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
let mut i = 0;
while i < IRQ_CHIP.irq_chip_list.chips.len() {
@@ -66,7 +74,10 @@ pub unsafe fn init() {
i += 1;
}
}
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx].ic.irq_xlate(&intr_data, 0).unwrap();
let virq = IRQ_CHIP.irq_chip_list.chips[ic_idx]
.ic
.irq_xlate(&intr_data, 0)
.unwrap();
info!("serial_port virq = {}", virq);
register_irq(virq as u32, Box::new(Com1Irq {}));
IRQ_CHIP.irq_enable(virq as u32);
+6 -7
View File
@@ -135,13 +135,14 @@ impl SerialPort {
}
pub fn write_reg(&self, register: u8, data: u32) {
unsafe { ptr::write_volatile((self.base + register as usize) as *mut u32, data); }
unsafe {
ptr::write_volatile((self.base + register as usize) as *mut u32, data);
}
}
pub fn init(&mut self, with_irq: bool) {
if self.skip_init {
return ;
return;
}
//Disable UART first
@@ -175,7 +176,7 @@ impl SerialPort {
}
pub fn drain_fifo(&mut self) {
for _ in 0..self.fifo_size*2 {
for _ in 0..self.fifo_size * 2 {
if self.line_sts().contains(UartFrFlags::RXFE) {
break;
}
@@ -187,7 +188,6 @@ impl SerialPort {
let mut flags = self.intr_stats();
let chk_flags = UartRisFlags::RTIS | UartRisFlags::RXIS;
while (flags & chk_flags).bits != 0 {
if self.cts_event_walkaround {
self.write_reg(self.intr_clr_reg, 0x00);
let _ = self.read_reg(self.intr_clr_reg);
@@ -213,7 +213,7 @@ impl SerialPort {
}
pub fn send(&mut self, data: u8) {
while ! self.line_sts().contains(UartFrFlags::TXFE) {}
while !self.line_sts().contains(UartFrFlags::TXFE) {}
self.write_reg(self.data_reg, data as u32);
}
@@ -227,7 +227,6 @@ impl SerialPort {
}
pub fn enable_irq(&mut self) {
self.clear_all_irqs();
self.drain_fifo();
+115 -36
View File
@@ -1,11 +1,13 @@
extern crate fdt;
extern crate byteorder;
extern crate fdt;
use crate::log::{info, debug};
use fdt::Node;
use core::slice;
use crate::memory::MemoryArea;
use self::byteorder::{ByteOrder, BE};
use crate::{
log::{debug, info},
memory::MemoryArea,
};
use core::slice;
use fdt::Node;
pub static mut MEMORY_MAP: [MemoryArea; 512] = [MemoryArea {
base_addr: 0,
@@ -16,29 +18,61 @@ pub static mut MEMORY_MAP: [MemoryArea; 512] = [MemoryArea {
pub fn root_cell_sz(dt: &fdt::DeviceTree) -> Option<(u32, u32)> {
let root_node = dt.nodes().nth(0).unwrap();
let address_cells = root_node.properties().find(|p| p.name.contains("#address-cells")).unwrap();
let size_cells = root_node.properties().find(|p| p.name.contains("#size-cells")).unwrap();
let address_cells = root_node
.properties()
.find(|p| p.name.contains("#address-cells"))
.unwrap();
let size_cells = root_node
.properties()
.find(|p| p.name.contains("#size-cells"))
.unwrap();
Some((BE::read_u32(&size_cells.data), BE::read_u32(&size_cells.data)))
Some((
BE::read_u32(&size_cells.data),
BE::read_u32(&size_cells.data),
))
}
pub fn travel_interrupt_ctrl(fdt: &fdt::DeviceTree) {
let root_node = fdt.nodes().nth(0).unwrap();
let intr = root_node.properties().find(|p| p.name.contains("interrupt-parent")).unwrap();
let intr = root_node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
.unwrap();
let root_intr_parent = BE::read_u32(&intr.data);
debug!("root parent = 0x{:08x}", root_intr_parent);
for node in fdt.nodes() {
if node.properties().find(|p| p.name.contains("interrupt-controller")).is_some() {
let compatible = node.properties().find(|p| p.name.contains("compatible")).unwrap();
let phandle = node.properties().find(|p| p.name.contains("phandle")).unwrap();
let intr_cells = node.properties().find(|p| p.name.contains("#interrupt-cells")).unwrap();
let _intr = node.properties().find(|p| p.name.contains("interrupt-parent"));
if node
.properties()
.find(|p| p.name.contains("interrupt-controller"))
.is_some()
{
let compatible = node
.properties()
.find(|p| p.name.contains("compatible"))
.unwrap();
let phandle = node
.properties()
.find(|p| p.name.contains("phandle"))
.unwrap();
let intr_cells = node
.properties()
.find(|p| p.name.contains("#interrupt-cells"))
.unwrap();
let _intr = node
.properties()
.find(|p| p.name.contains("interrupt-parent"));
let _intr_data = node.properties().find(|p| p.name.contains("interrupts"));
let s = core::str::from_utf8(compatible.data).unwrap();
debug!("{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}", node.name, s, BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data));
debug!(
"{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}",
node.name,
s,
BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data)
);
if let Some(intr) = _intr {
if let Some(intr_data) = _intr_data {
debug!("interrupt-parent = 0x{:08x}", BE::read_u32(intr.data));
@@ -53,10 +87,17 @@ pub fn travel_interrupt_ctrl(fdt: &fdt::DeviceTree) {
}
}
fn memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usize, ranges: &mut [(usize, usize); 10]) -> usize {
fn memory_ranges(
dt: &fdt::DeviceTree,
address_cells: usize,
size_cells: usize,
ranges: &mut [(usize, usize); 10],
) -> usize {
let (memory_node, _memory_cells) = dt.find_node("/memory").unwrap();
let reg = memory_node.properties().find(|p| p.name.contains("reg")).unwrap();
let reg = memory_node
.properties()
.find(|p| p.name.contains("reg"))
.unwrap();
let chunk_sz = (address_cells + size_cells) * 4;
let chunk_count = (reg.data.len() / chunk_sz);
let mut index = 0;
@@ -79,8 +120,12 @@ fn memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usize,
index
}
fn dev_memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usize, ranges: &mut [(usize, usize); 10]) -> usize {
fn dev_memory_ranges(
dt: &fdt::DeviceTree,
address_cells: usize,
size_cells: usize,
ranges: &mut [(usize, usize); 10],
) -> usize {
// work around for qemu-arm64
// dev mem: 128MB - 1GB, see https://github.com/qemu/qemu/blob/master/hw/arm/virt.c for details
let root_node = dt.nodes().nth(0).unwrap();
@@ -100,7 +145,10 @@ fn dev_memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usi
}
let (memory_node, _memory_cells) = dt.find_node("/soc").unwrap();
let reg = memory_node.properties().find(|p| p.name.contains("ranges")).unwrap();
let reg = memory_node
.properties()
.find(|p| p.name.contains("ranges"))
.unwrap();
let chunk_sz = (address_cells * 2 + size_cells) * 4;
let chunk_count = (reg.data.len() / chunk_sz);
let mut index = 0;
@@ -137,7 +185,10 @@ fn dev_memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usi
return 0;
}
};
debug!("dev mem 0x{:08x} 0x{:08x} 0x{:08x}", child_bus_addr, parent_bus_addr, addr_size);
debug!(
"dev mem 0x{:08x} 0x{:08x} 0x{:08x}",
child_bus_addr, parent_bus_addr, addr_size
);
ranges[index] = (parent_bus_addr as usize, addr_size as usize);
index += 1;
@@ -150,17 +201,33 @@ pub fn diag_uart_range(dtb_base: usize, dtb_size: usize) -> Option<(usize, usize
let dt = fdt::DeviceTree::new(data).unwrap();
let (chosen_node, _chosen_cells) = dt.find_node("/chosen").unwrap();
let stdout_path = chosen_node.properties().find(|p| p.name.contains("stdout-path")).unwrap();
let uart_node_name = core::str::from_utf8(stdout_path.data).unwrap()
let stdout_path = chosen_node
.properties()
.find(|p| p.name.contains("stdout-path"))
.unwrap();
let uart_node_name = core::str::from_utf8(stdout_path.data)
.unwrap()
.split('/')
.nth(1)?
.trim_end();
let len = uart_node_name.len();
let uart_node_name = &uart_node_name[0..len-1];
let uart_node = dt.nodes().find(|n| n.name.contains(uart_node_name)).unwrap();
let skip_init = uart_node.properties().find(|p| p.name.contains("skip-init")).is_some();
let cts_event_walkaround = uart_node.properties().find(|p| p.name.contains("cts-event-walkaround")).is_some();
let reg = uart_node.properties().find(|p| p.name.contains("reg")).unwrap();
let uart_node_name = &uart_node_name[0..len - 1];
let uart_node = dt
.nodes()
.find(|n| n.name.contains(uart_node_name))
.unwrap();
let skip_init = uart_node
.properties()
.find(|p| p.name.contains("skip-init"))
.is_some();
let cts_event_walkaround = uart_node
.properties()
.find(|p| p.name.contains("cts-event-walkaround"))
.is_some();
let reg = uart_node
.properties()
.find(|p| p.name.contains("reg"))
.unwrap();
let (address_cells, size_cells) = root_cell_sz(&dt).unwrap();
let chunk_sz = (address_cells + size_cells) * 4;
@@ -188,7 +255,10 @@ fn compatible_node_present<'a>(dt: &fdt::DeviceTree<'a>, compat_string: &str) ->
false
}
pub fn find_compatible_node<'a>(dt: &'a fdt::DeviceTree<'a>, compat_string: &str) -> Option<Node<'a, 'a>> {
pub fn find_compatible_node<'a>(
dt: &'a fdt::DeviceTree<'a>,
compat_string: &str,
) -> Option<Node<'a, 'a>> {
for node in dt.nodes() {
if let Some(compatible) = node.properties().find(|p| p.name.contains("compatible")) {
let s = core::str::from_utf8(compatible.data).unwrap();
@@ -205,10 +275,14 @@ pub fn fill_env_data(dtb_base: usize, dtb_size: usize, env_base: usize) -> usize
let dt = fdt::DeviceTree::new(data).unwrap();
let (chosen_node, _chosen_cells) = dt.find_node("/chosen").unwrap();
if let Some(bootargs) = chosen_node.properties().find(|p| p.name.contains("bootargs")) {
if let Some(bootargs) = chosen_node
.properties()
.find(|p| p.name.contains("bootargs"))
{
let bootargs_len = bootargs.data.len();
let env_base_slice = unsafe { slice::from_raw_parts_mut(env_base as *mut u8, bootargs_len) };
let env_base_slice =
unsafe { slice::from_raw_parts_mut(env_base as *mut u8, bootargs_len) };
env_base_slice[..bootargs_len].clone_from_slice(bootargs.data);
bootargs_len
@@ -222,11 +296,16 @@ pub fn fill_memory_map(dtb_base: usize, dtb_size: usize) {
let dt = fdt::DeviceTree::new(data).unwrap();
let (address_cells, size_cells) = root_cell_sz(&dt).unwrap();
let mut ranges: [(usize, usize); 10] = [(0,0); 10];
let mut ranges: [(usize, usize); 10] = [(0, 0); 10];
//in uefi boot mode, ignore memory node, just read the device memory range
//in uefi boot mode, ignore memory node, just read the device memory range
//let nranges = memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges);
let nranges = dev_memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges);
let nranges = dev_memory_ranges(
&dt,
address_cells as usize,
size_cells as usize,
&mut ranges,
);
for index in 0..nranges {
let (base, size) = ranges[index];
+43 -21
View File
@@ -1,13 +1,12 @@
use rmm::VirtualAddress;
use crate::memory::{ArchIntCtx, GenericPfFlags};
use crate::{
exception_stack,
interrupt::stack_trace,
memory::{ArchIntCtx, GenericPfFlags},
syscall,
syscall::flag::*,
with_exception_stack,
exception_stack,
};
use super::InterruptStack;
@@ -32,7 +31,12 @@ unsafe fn far_el1() -> usize {
ret
}
unsafe fn instr_data_abort_inner(stack: &mut InterruptStack, from_user: bool, instr_not_data: bool, from: &str) -> bool {
unsafe fn instr_data_abort_inner(
stack: &mut InterruptStack,
from_user: bool,
instr_not_data: bool,
from: &str,
) -> bool {
let iss = iss(stack.iret.esr_el1);
let fsc = iss & 0x3F;
//dbg!(fsc);
@@ -46,7 +50,10 @@ unsafe fn instr_data_abort_inner(stack: &mut InterruptStack, from_user: bool, in
// TODO: RMW instructions may "involve" writing to (possibly invalid) memory, but AArch64
// doesn't appear to require that flag to be set if the read alone would trigger a fault.
flags.set(GenericPfFlags::INVOLVED_WRITE, write_not_read_if_data && !instr_not_data);
flags.set(
GenericPfFlags::INVOLVED_WRITE,
write_not_read_if_data && !instr_not_data,
);
flags.set(GenericPfFlags::INSTR_NOT_DATA, instr_not_data);
flags.set(GenericPfFlags::USER_NOT_SUPERVISOR, from_user);
@@ -74,7 +81,12 @@ unsafe fn cntvct_el0() -> usize {
ret
}
unsafe fn instr_trapped_msr_mrs_inner(stack: &mut InterruptStack, from_user: bool, instr_not_data: bool, from: &str) -> bool {
unsafe fn instr_trapped_msr_mrs_inner(
stack: &mut InterruptStack,
from_user: bool,
instr_not_data: bool,
from: &str,
) -> bool {
let iss = iss(stack.iret.esr_el1);
let res0 = (iss & 0x1C0_0000) >> 22;
let op0 = (iss & 0x030_0000) >> 20;
@@ -99,7 +111,7 @@ unsafe fn instr_trapped_msr_mrs_inner(stack: &mut InterruptStack, from_user: boo
stack.store_reg(rt as usize, reg_val);
//skip faulting instruction, A64 instructions are always 32-bits
stack.iret.elr_el1 += 4;
return true
return true;
}
//MRS <Xt>, CNTPCT_EL0
(0b11, 0b011, 0b1110, 0b0000, 0b001, 0b1) => {
@@ -107,7 +119,7 @@ unsafe fn instr_trapped_msr_mrs_inner(stack: &mut InterruptStack, from_user: boo
stack.store_reg(rt as usize, reg_val);
//skip faulting instruction, A64 instructions are always 32-bits
stack.iret.elr_el1 += 4;
return true
return true;
}
//MRS <Xt>, CNTVCT_EL0
(0b11, 0b011, 0b1110, 0b0000, 0b010, 0b1) => {
@@ -115,22 +127,25 @@ unsafe fn instr_trapped_msr_mrs_inner(stack: &mut InterruptStack, from_user: boo
stack.store_reg(rt as usize, reg_val);
//skip faulting instruction, A64 instructions are always 32-bits
stack.iret.elr_el1 += 4;
return true
return true;
}
_ => {},
_ => {}
}
false
}
exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
if !pf_inner(stack, exception_code(stack.iret.esr_el1), "sync_exc_el1_spx") {
if !pf_inner(
stack,
exception_code(stack.iret.esr_el1),
"sync_exc_el1_spx",
) {
println!("Synchronous exception at EL1 with SPx");
if exception_code(stack.iret.esr_el1) == 0b100101 {
let far_el1 = far_el1();
println!("FAR_EL1 = 0x{:08x}", far_el1);
}
else if exception_code(stack.iret.esr_el1) == 0b100100 {
} else if exception_code(stack.iret.esr_el1) == 0b100100 {
let far_el1 = far_el1();
println!("USER FAR_EL1 = 0x{:08x}", far_el1);
}
@@ -160,16 +175,23 @@ exception_stack!(synchronous_exception_at_el0, |stack| {
match exception_code(stack.iret.esr_el1) {
0b010101 => with_exception_stack!(|stack| {
let scratch = &stack.scratch;
syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack)
syscall::syscall(
scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack,
)
}),
ty => if !pf_inner(stack, ty as u8, "sync_exc_el0") {
log::error!("FATAL: Not an SVC induced synchronous exception (ty={:b})", ty);
println!("FAR_EL1: {:#0x}", far_el1());
//crate::debugger::debugger(None);
stack.dump();
stack_trace();
crate::ksignal(SIGSEGV);
ty => {
if !pf_inner(stack, ty as u8, "sync_exc_el0") {
log::error!(
"FATAL: Not an SVC induced synchronous exception (ty={:b})",
ty
);
println!("FAR_EL1: {:#0x}", far_el1());
//crate::debugger::debugger(None);
stack.dump();
stack_trace();
crate::ksignal(SIGSEGV);
}
}
}
});
+31 -17
View File
@@ -87,9 +87,9 @@ impl PreservedRegisters {
#[derive(Default)]
#[repr(packed)]
pub struct IretRegisters {
// occurred
// The exception vector disambiguates at which EL the interrupt
pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1
// occurred
// The exception vector disambiguates at which EL the interrupt
pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1
pub esr_el1: usize,
pub spsr_el1: usize,
pub elr_el1: usize,
@@ -238,12 +238,14 @@ impl InterruptStack {
28 => self.preserved.x28 = val,
29 => self.preserved.x29 = val,
30 => self.preserved.x30 = val,
_ => {},
_ => {}
}
}
//TODO
pub fn is_singlestep(&self) -> bool { false }
pub fn is_singlestep(&self) -> bool {
false
}
pub fn set_singlestep(&mut self, singlestep: bool) {}
}
@@ -276,7 +278,8 @@ macro_rules! function {
#[macro_export]
macro_rules! push_scratch {
() => { "
() => {
"
// Push scratch registers
str x18, [sp, #-16]!
stp x16, x17, [sp, #-16]!
@@ -288,12 +291,14 @@ macro_rules! push_scratch {
stp x4, x5, [sp, #-16]!
stp x2, x3, [sp, #-16]!
stp x0, x1, [sp, #-16]!
" };
"
};
}
#[macro_export]
macro_rules! pop_scratch {
() => { "
() => {
"
// Pop scratch registers
ldp x0, x1, [sp], #16
ldp x2, x3, [sp], #16
@@ -305,12 +310,14 @@ macro_rules! pop_scratch {
ldp x14, x15, [sp], #16
ldp x16, x17, [sp], #16
ldr x18, [sp], #16
" };
"
};
}
#[macro_export]
macro_rules! push_preserved {
() => { "
() => {
"
// Push preserved registers
stp x29, x30, [sp, #-16]!
stp x27, x28, [sp, #-16]!
@@ -318,12 +325,14 @@ macro_rules! push_preserved {
stp x23, x24, [sp, #-16]!
stp x21, x22, [sp, #-16]!
stp x19, x20, [sp, #-16]!
" };
"
};
}
#[macro_export]
macro_rules! pop_preserved {
() => { "
() => {
"
// Pop preserved registers
ldp x19, x20, [sp], #16
ldp x21, x22, [sp], #16
@@ -331,12 +340,14 @@ macro_rules! pop_preserved {
ldp x25, x26, [sp], #16
ldp x27, x28, [sp], #16
ldp x29, x30, [sp], #16
" };
"
};
}
#[macro_export]
macro_rules! push_special {
() => { "
() => {
"
mrs x14, spsr_el1
mrs x15, elr_el1
stp x14, x15, [sp, #-16]!
@@ -344,12 +355,14 @@ macro_rules! push_special {
mrs x14, sp_el0
mrs x15, esr_el1
stp x14, x15, [sp, #-16]!
" };
"
};
}
#[macro_export]
macro_rules! pop_special {
() => { "
() => {
"
ldp x14, x15, [sp], 16
msr esr_el1, x15
msr sp_el0, x14
@@ -357,7 +370,8 @@ macro_rules! pop_special {
ldp x14, x15, [sp], 16
msr elr_el1, x15
msr spsr_el1, x14
" };
"
};
}
#[macro_export]
+2 -4
View File
@@ -1,6 +1,5 @@
//use crate::device::generic_timer::{GENTIMER};
use crate::device::irqchip::IRQ_CHIP;
use crate::device::serial::COM1;
use crate::device::{irqchip::IRQ_CHIP, serial::COM1};
pub struct IrqDesc {
pub virq: u32,
@@ -33,10 +32,9 @@ exception_stack!(irq_at_el1, |stack| {
}
});
//TODO
pub unsafe fn trigger(irq: u32) {
extern {
extern "C" {
fn irq_trigger(irq: u32);
}
+1 -2
View File
@@ -12,8 +12,7 @@ pub mod trace;
use crate::LogicalCpuId;
pub use self::handler::InterruptStack;
pub use self::trace::stack_trace;
pub use self::{handler::InterruptStack, trace::stack_trace};
/// Clear interrupts
#[inline(always)]
+8 -9
View File
@@ -1,15 +1,14 @@
use crate::{
arch::{interrupt::InterruptStack},
context,
syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL},
arch::interrupt::InterruptStack,
context, syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_POST_SYSCALL, PTRACE_STOP_PRE_SYSCALL},
};
#[no_mangle]
pub unsafe extern fn do_exception_unhandled() {}
pub unsafe extern "C" fn do_exception_unhandled() {}
#[no_mangle]
pub unsafe extern fn do_exception_synchronous() {}
pub unsafe extern "C" fn do_exception_synchronous() {}
#[allow(dead_code)]
#[repr(packed)]
@@ -57,7 +56,7 @@ pub struct SyscallStack {
#[macro_export]
macro_rules! with_exception_stack {
(|$stack:ident| $code:block) => {{
let $stack = &mut *$stack;
(*$stack).scratch.x0 = $code;
}}
let $stack = &mut *$stack;
(*$stack).scratch.x0 = $code;
}};
}
+76 -70
View File
@@ -18,7 +18,8 @@ pub unsafe fn stack_trace() {
for _frame in 0..64 {
if let Some(pc_fp) = fp.checked_add(mem::size_of::<usize>()) {
if mapper.translate(VirtualAddress::new(fp)).is_some()
&& mapper.translate(VirtualAddress::new(pc_fp)).is_some() {
&& mapper.translate(VirtualAddress::new(pc_fp)).is_some()
{
let pc = *(pc_fp as *const usize);
if pc == 0 {
println!(" {:>016x}: EMPTY RETURN", fp);
@@ -41,11 +42,12 @@ pub unsafe fn stack_trace() {
//TODO: Do not create Elf object for every symbol lookup
#[inline(never)]
pub unsafe fn symbol_trace(addr: usize) {
use core::slice;
use core::sync::atomic::Ordering;
use core::{slice, sync::atomic::Ordering};
use crate::elf::Elf;
use crate::start::{KERNEL_BASE, KERNEL_SIZE};
use crate::{
elf::Elf,
start::{KERNEL_BASE, KERNEL_SIZE},
};
let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::KERNEL_OFFSET) as *const u8;
let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));
@@ -70,76 +72,80 @@ pub unsafe fn symbol_trace(addr: usize) {
for sym in symbols {
if sym::st_type(sym.st_info) == sym::STT_FUNC
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
{
println!(" {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize);
&& addr < (sym.st_value + sym.st_size) as usize
{
println!(
" {:>016X}+{:>04X}",
sym.st_value,
addr - sym.st_value as usize
);
if let Some(strtab) = strtab_opt {
let start = strtab.sh_offset as usize + sym.st_name as usize;
let mut end = start;
while end < elf.data.len() {
let b = elf.data[end];
end += 1;
if b == 0 {
break;
}
}
if end > start {
let sym_name = &elf.data[start .. end];
print!(" ");
if sym_name.starts_with(b"_ZN") {
// Skip _ZN
let mut i = 3;
let mut first = true;
while i < sym_name.len() {
// E is the end character
if sym_name[i] == b'E' {
break;
}
// Parse length string
let mut len = 0;
while i < sym_name.len() {
let b = sym_name[i];
if b >= b'0' && b <= b'9' {
i += 1;
len *= 10;
len += (b - b'0') as usize;
} else {
break;
}
}
// Print namespace seperator, if required
if first {
first = false;
} else {
print!("::");
}
// Print name string
let end = i + len;
while i < sym_name.len() && i < end {
print!("{}", sym_name[i] as char);
i += 1;
}
}
} else {
for &b in sym_name.iter() {
print!("{}", b as char);
}
}
println!("");
}
if let Some(strtab) = strtab_opt {
let start = strtab.sh_offset as usize + sym.st_name as usize;
let mut end = start;
while end < elf.data.len() {
let b = elf.data[end];
end += 1;
if b == 0 {
break;
}
}
if end > start {
let sym_name = &elf.data[start..end];
print!(" ");
if sym_name.starts_with(b"_ZN") {
// Skip _ZN
let mut i = 3;
let mut first = true;
while i < sym_name.len() {
// E is the end character
if sym_name[i] == b'E' {
break;
}
// Parse length string
let mut len = 0;
while i < sym_name.len() {
let b = sym_name[i];
if b >= b'0' && b <= b'9' {
i += 1;
len *= 10;
len += (b - b'0') as usize;
} else {
break;
}
}
// Print namespace seperator, if required
if first {
first = false;
} else {
print!("::");
}
// Print name string
let end = i + len;
while i < sym_name.len() && i < end {
print!("{}", sym_name[i] as char);
i += 1;
}
}
} else {
for &b in sym_name.iter() {
print!("{}", b as char);
}
}
println!("");
}
}
}
}
}
},
}
Err(_e) => {
println!("WTF ?");
}
+5 -3
View File
@@ -1,6 +1,8 @@
use crate::LogicalCpuId;
use crate::paging::{RmmA, RmmArch};
use crate::percpu::PercpuBlock;
use crate::{
paging::{RmmA, RmmArch},
percpu::PercpuBlock,
LogicalCpuId,
};
impl PercpuBlock {
pub fn current() -> &'static Self {
+10 -4
View File
@@ -46,7 +46,8 @@ pub use arch_copy_to_user as arch_copy_from_user;
#[link_section = ".usercopy-fns"]
pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -> u8 {
// x0, x1, x2
core::arch::asm!("
core::arch::asm!(
"
mov x4, x0
mov x0, 0
2:
@@ -63,13 +64,18 @@ pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -
b 2b
3:
ret
", options(noreturn));
",
options(noreturn)
);
}
pub unsafe fn bootstrap_mem(bootstrap: &crate::Bootstrap) -> &'static [u8] {
use ::rmm::Arch;
use crate::memory::PAGE_SIZE;
use ::rmm::Arch;
core::slice::from_raw_parts(CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8, bootstrap.page_count * PAGE_SIZE)
core::slice::from_raw_parts(
CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8,
bootstrap.page_count * PAGE_SIZE,
)
}
pub const KFX_SIZE: usize = 1024;
-1
View File
@@ -11,4 +11,3 @@ bitflags! {
const DEV_MEM = 2 << 2;
}
}
+9 -3
View File
@@ -4,16 +4,22 @@ use super::RmmA;
pub use rmm::{Flusher, PageFlush, PageFlushAll};
pub struct InactiveFlusher { _inner: () }
pub struct InactiveFlusher {
_inner: (),
}
impl InactiveFlusher {
// TODO: cpu id
pub fn new() -> Self { Self { _inner: () } }
pub fn new() -> Self {
Self { _inner: () }
}
}
impl Flusher<RmmA> for InactiveFlusher {
fn consume(&mut self, flush: PageFlush<RmmA>) {
// TODO: Push to TLB "mailbox" or tell it to reload CR3 if there are too many entries.
unsafe { flush.ignore(); }
unsafe {
flush.ignore();
}
}
}
impl Drop for InactiveFlusher {
+5 -9
View File
@@ -7,15 +7,8 @@ use crate::device::cpu::registers::{control_regs, tlb};
use self::mapper::PageFlushAll;
pub use rmm::{
Arch as RmmArch,
Flusher,
PageFlags,
PhysicalAddress,
TableKind,
VirtualAddress,
};
pub use super::CurrentRmmArch as RmmA;
pub use rmm::{Arch as RmmArch, Flusher, PageFlags, PhysicalAddress, TableKind, VirtualAddress};
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
pub use crate::rmm::KernelMapper;
@@ -83,7 +76,10 @@ impl Page {
}
pub fn range_inclusive(start: Page, r#final: Page) -> PageIter {
PageIter { start, end: r#final.next() }
PageIter {
start,
end: r#final.next(),
}
}
pub fn range_exclusive(start: Page, end: Page) -> PageIter {
PageIter { start, end }
+144 -98
View File
@@ -1,28 +1,15 @@
use core::{
cmp,
mem,
slice,
sync::atomic::{self, AtomicUsize, Ordering}, cell::SyncUnsafeCell,
cell::SyncUnsafeCell,
cmp, mem, slice,
sync::atomic::{self, AtomicUsize, Ordering},
};
use rmm::{
KILOBYTE,
MEGABYTE,
Arch,
BuddyAllocator,
BumpAllocator,
FrameAllocator,
FrameCount,
FrameUsage,
MemoryArea,
PageFlags,
PageMapper,
PhysicalAddress,
TableKind,
VirtualAddress,
Arch, BuddyAllocator, BumpAllocator, FrameAllocator, FrameCount, FrameUsage, MemoryArea,
PageFlags, PageMapper, PhysicalAddress, TableKind, VirtualAddress, KILOBYTE, MEGABYTE,
};
use spin::Mutex;
use crate::{LogicalCpuId, init::device_tree::MEMORY_MAP, paging::entry::EntryFlags};
use crate::{init::device_tree::MEMORY_MAP, paging::entry::EntryFlags, LogicalCpuId};
use super::CurrentRmmArch as RmmA;
@@ -63,11 +50,16 @@ unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> PageFlags<A> {
unsafe fn inner<A: Arch>(
areas: &'static [MemoryArea],
kernel_base: usize, kernel_size_aligned: usize,
stack_base: usize, stack_size_aligned: usize,
env_base: usize, env_size_aligned: usize,
acpi_base: usize, acpi_size_aligned: usize,
initfs_base: usize, initfs_size_aligned: usize,
kernel_base: usize,
kernel_size_aligned: usize,
stack_base: usize,
stack_size_aligned: usize,
env_base: usize,
env_size_aligned: usize,
acpi_base: usize,
acpi_size_aligned: usize,
initfs_base: usize,
initfs_size_aligned: usize,
) -> BuddyAllocator<A> {
// First, calculate how much memory we have
let mut size = 0;
@@ -84,10 +76,8 @@ unsafe fn inner<A: Arch>(
let mut bump_allocator = BumpAllocator::<A>::new(areas, 0);
{
let mut mapper = PageMapper::<A, _>::create(
TableKind::Kernel,
&mut bump_allocator
).expect("failed to create Mapper");
let mut mapper = PageMapper::<A, _>::create(TableKind::Kernel, &mut bump_allocator)
.expect("failed to create Mapper");
// Map all physical areas at PHYS_OFFSET
for area in areas.iter() {
@@ -95,11 +85,9 @@ unsafe fn inner<A: Arch>(
let phys = area.base.add(i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -109,19 +97,15 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(kernel_base + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(crate::KERNEL_OFFSET + i * A::PAGE_SIZE);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
let virt = A::phys_to_virt(phys);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
@@ -131,11 +115,9 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
};
@@ -163,7 +145,8 @@ unsafe fn inner<A: Arch>(
//map dev mem
for mem in MEMORY_MAP {
if mem._type == 2 {
let size_aligned = ((mem.length as usize + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let size_aligned =
((mem.length as usize + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let base = mem.base_addr as usize;
for i in 0..size_aligned / A::PAGE_SIZE {
let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE);
@@ -171,13 +154,10 @@ unsafe fn inner<A: Arch>(
// use the same mair_el1 value with bootloader,
// mair_el1 == 0x00000000000044FF
// set mem_attr == device memory
let flags = page_flags::<A>(virt)
.custom_flag(EntryFlags::DEV_MEM.bits(), true);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flags = page_flags::<A>(virt).custom_flag(EntryFlags::DEV_MEM.bits(), true);
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -195,12 +175,10 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(phys + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(virt + i * A::PAGE_SIZE);
let flags = PageFlags::new().write(true);
//TODO: Write combining flag
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
//TODO: Write combining flag
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -220,7 +198,10 @@ unsafe fn inner<A: Arch>(
// Create the physical memory map
let offset = bump_allocator.offset();
log::info!("Permanently used: {} KB", (offset + (KILOBYTE - 1)) / KILOBYTE);
log::info!(
"Permanently used: {} KB",
(offset + (KILOBYTE - 1)) / KILOBYTE
);
BuddyAllocator::<A>::new(bump_allocator).expect("failed to create BuddyAllocator")
}
@@ -264,10 +245,12 @@ impl core::fmt::Debug for LockedAllocator {
}
}
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new([MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512]);
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new(
[MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512],
);
static AREA_COUNT: SyncUnsafeCell<u16> = SyncUnsafeCell::new(0);
// TODO: Share code
@@ -300,7 +283,12 @@ pub struct KernelMapper {
impl KernelMapper {
fn lock_inner(current_processor: usize) -> bool {
loop {
match LOCK_OWNER.compare_exchange_weak(NO_PROCESSOR, current_processor, Ordering::Acquire, Ordering::Relaxed) {
match LOCK_OWNER.compare_exchange_weak(
NO_PROCESSOR,
current_processor,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => break,
// already owned by this hardware thread
Err(id) if id == current_processor => break,
@@ -314,15 +302,20 @@ impl KernelMapper {
prev_count > 0
}
pub unsafe fn lock_for_manual_mapper(current_processor: LogicalCpuId, mapper: crate::paging::PageMapper) -> Self {
pub unsafe fn lock_for_manual_mapper(
current_processor: LogicalCpuId,
mapper: crate::paging::PageMapper,
) -> Self {
let ro = Self::lock_inner(current_processor.get() as usize);
Self {
mapper,
ro,
}
Self { mapper, ro }
}
pub fn lock_manually(current_processor: LogicalCpuId) -> Self {
unsafe { Self::lock_for_manual_mapper(current_processor, PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR)) }
unsafe {
Self::lock_for_manual_mapper(
current_processor,
PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR),
)
}
}
pub fn lock() -> Self {
Self::lock_manually(crate::cpu_id())
@@ -357,12 +350,18 @@ impl Drop for KernelMapper {
}
pub unsafe fn init(
kernel_base: usize, kernel_size: usize,
stack_base: usize, stack_size: usize,
env_base: usize, env_size: usize,
acpi_base: usize, acpi_size: usize,
areas_base: usize, areas_size: usize,
initfs_base: usize, initfs_size: usize,
kernel_base: usize,
kernel_size: usize,
stack_base: usize,
stack_size: usize,
env_base: usize,
env_size: usize,
acpi_base: usize,
acpi_size: usize,
areas_base: usize,
areas_size: usize,
initfs_base: usize,
initfs_size: usize,
) {
type A = RmmA;
@@ -370,24 +369,24 @@ pub unsafe fn init(
let real_size = 0x100000;
let real_end = real_base + real_size;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_end = kernel_base + kernel_size_aligned;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_end = stack_base + stack_size_aligned;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let env_end = env_base + env_size_aligned;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_end = acpi_base + acpi_size_aligned;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_end = initfs_base + initfs_size_aligned;
let bootloader_areas = slice::from_raw_parts(
areas_base as *const BootloaderMemoryEntry,
areas_size / mem::size_of::<BootloaderMemoryEntry>()
areas_size / mem::size_of::<BootloaderMemoryEntry>(),
);
let areas = &mut *AREAS.get();
@@ -422,42 +421,84 @@ pub unsafe fn init(
// Ensure real-mode areas are not used
if base < real_end && base + size > real_base {
log::warn!("{:X}:{:X} overlaps with real mode {:X}:{:X}", base, size, real_base, real_size);
log::warn!(
"{:X}:{:X} overlaps with real mode {:X}:{:X}",
base,
size,
real_base,
real_size
);
new_base = cmp::max(new_base, real_end);
}
// Ensure kernel areas are not used
if base < kernel_end && base + size > kernel_base {
log::warn!("{:X}:{:X} overlaps with kernel {:X}:{:X}", base, size, kernel_base, kernel_size);
log::warn!(
"{:X}:{:X} overlaps with kernel {:X}:{:X}",
base,
size,
kernel_base,
kernel_size
);
new_base = cmp::max(new_base, kernel_end);
}
// Ensure stack areas are not used
if base < stack_end && base + size > stack_base {
log::warn!("{:X}:{:X} overlaps with stack {:X}:{:X}", base, size, stack_base, stack_size);
log::warn!(
"{:X}:{:X} overlaps with stack {:X}:{:X}",
base,
size,
stack_base,
stack_size
);
new_base = cmp::max(new_base, stack_end);
}
// Ensure env areas are not used
if base < env_end && base + size > env_base {
log::warn!("{:X}:{:X} overlaps with env {:X}:{:X}", base, size, env_base, env_size);
log::warn!(
"{:X}:{:X} overlaps with env {:X}:{:X}",
base,
size,
env_base,
env_size
);
new_base = cmp::max(new_base, env_end);
}
// Ensure acpi areas are not used
if base < acpi_end && base + size > acpi_base {
log::warn!("{:X}:{:X} overlaps with acpi {:X}:{:X}", base, size, acpi_base, acpi_size);
log::warn!(
"{:X}:{:X} overlaps with acpi {:X}:{:X}",
base,
size,
acpi_base,
acpi_size
);
new_base = cmp::max(new_base, acpi_end);
}
if base < initfs_end && base + size > initfs_base {
log::warn!("{:X}:{:X} overlaps with initfs {:X}:{:X}", base, size, initfs_base, initfs_size);
log::warn!(
"{:X}:{:X} overlaps with initfs {:X}:{:X}",
base,
size,
initfs_base,
initfs_size
);
new_base = cmp::max(new_base, initfs_end);
}
if new_base != base {
let end = base + size;
let new_size = end.checked_sub(new_base).unwrap_or(0);
log::info!("{:X}:{:X} moved to {:X}:{:X}", base, size, new_base, new_size);
log::info!(
"{:X}:{:X} moved to {:X}:{:X}",
base,
size,
new_base,
new_size
);
base = new_base;
size = new_size;
}
@@ -475,11 +516,16 @@ pub unsafe fn init(
let allocator = inner::<A>(
areas,
kernel_base, kernel_size_aligned,
stack_base, stack_size_aligned,
env_base, env_size_aligned,
acpi_base, acpi_size_aligned,
initfs_base, initfs_size_aligned,
kernel_base,
kernel_size_aligned,
stack_base,
stack_size_aligned,
env_base,
env_size_aligned,
acpi_base,
acpi_size_aligned,
initfs_base,
initfs_size_aligned,
);
*INNER_ALLOCATOR.lock() = Some(allocator);
}
+66 -29
View File
@@ -2,21 +2,23 @@
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, AtomicU32};
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
use crate::memory::{Frame};
use crate::paging::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use crate::{
memory::Frame,
paging::{Page, PhysicalAddress, VirtualAddress, PAGE_SIZE},
};
use crate::{allocator, dtb};
use crate::device;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug;
use crate::init::device_tree;
use crate::interrupt;
use crate::log::{self, info};
use crate::paging::{self, KernelMapper};
use crate::{
allocator, device, dtb,
init::device_tree,
interrupt,
log::{self, info},
paging::{self, KernelMapper},
};
/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
@@ -71,7 +73,10 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
}
// Convert env to slice
let env = slice::from_raw_parts((crate::PHYS_OFFSET + args.env_base) as *const u8, args.env_size);
let env = slice::from_raw_parts(
(crate::PHYS_OFFSET + args.env_base) as *const u8,
args.env_size,
);
// Set up graphical debug
//#[cfg(feature = "graphical_debug")]
@@ -90,13 +95,37 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
});
info!("Redox OS starting...");
info!("Kernel: {:X}:{:X}", {args.kernel_base}, args.kernel_base + args.kernel_size);
info!("Stack: {:X}:{:X}", {args.stack_base}, args.stack_base + args.stack_size);
info!("Env: {:X}:{:X}", {args.env_base}, args.env_base + args.env_size);
info!("RSDPs: {:X}:{:X}", {args.dtb_base}, args.dtb_base + args.dtb_size);
info!("Areas: {:X}:{:X}", {args.areas_base}, args.areas_base + args.areas_size);
info!("Bootstrap: {:X}:{:X}", {args.bootstrap_base}, args.bootstrap_base + args.bootstrap_size);
info!("Bootstrap entry point: {:X}", {args.bootstrap_entry});
info!(
"Kernel: {:X}:{:X}",
{ args.kernel_base },
args.kernel_base + args.kernel_size
);
info!(
"Stack: {:X}:{:X}",
{ args.stack_base },
args.stack_base + args.stack_size
);
info!(
"Env: {:X}:{:X}",
{ args.env_base },
args.env_base + args.env_size
);
info!(
"RSDPs: {:X}:{:X}",
{ args.dtb_base },
args.dtb_base + args.dtb_size
);
info!(
"Areas: {:X}:{:X}",
{ args.areas_base },
args.areas_base + args.areas_size
);
info!(
"Bootstrap: {:X}:{:X}",
{ args.bootstrap_base },
args.bootstrap_base + args.bootstrap_size
);
info!("Bootstrap entry point: {:X}", { args.bootstrap_entry });
// Setup interrupt handlers
core::arch::asm!(
@@ -108,8 +137,8 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
);
if args.dtb_base != 0 {
//Try to read device memory map
device_tree::fill_memory_map(crate::PHYS_OFFSET + args.dtb_base, args.dtb_size);
//Try to read device memory map
device_tree::fill_memory_map(crate::PHYS_OFFSET + args.dtb_base, args.dtb_size);
}
/* NOT USED WITH UEFI
@@ -118,12 +147,18 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
// Initialize RMM
crate::arch::rmm::init(
args.kernel_base, args.kernel_size,
args.stack_base, args.stack_size,
args.env_base, args.env_size,
args.dtb_base, args.dtb_size,
args.areas_base, args.areas_size,
args.bootstrap_base, args.bootstrap_size,
args.kernel_base,
args.kernel_size,
args.stack_base,
args.stack_size,
args.env_base,
args.env_size,
args.dtb_base,
args.dtb_size,
args.areas_base,
args.areas_size,
args.bootstrap_base,
args.bootstrap_size,
);
// Initialize paging
@@ -163,7 +198,9 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
BSP_READY.store(true, Ordering::SeqCst);
crate::Bootstrap {
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(args.bootstrap_base)),
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(
args.bootstrap_base,
)),
page_count: args.bootstrap_size / crate::memory::PAGE_SIZE,
entry: args.bootstrap_entry,
env,
@@ -182,8 +219,8 @@ pub struct KernelArgsAp {
}
/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
loop{}
pub unsafe extern "C" fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
loop {}
}
#[naked]
+2 -2
View File
@@ -1,7 +1,7 @@
use core::arch::asm;
#[no_mangle]
pub unsafe extern fn kreset() -> ! {
pub unsafe extern "C" fn kreset() -> ! {
println!("kreset");
let val: u32 = 0x8400_0009;
@@ -16,7 +16,7 @@ pub unsafe fn emergency_reset() -> ! {
}
#[no_mangle]
pub unsafe extern fn kstop() -> ! {
pub unsafe extern "C" fn kstop() -> ! {
println!("kstop");
let val: u32 = 0x8400_0008;
+3 -2
View File
@@ -1,5 +1,5 @@
core::arch::global_asm!(
"
"
// Exception vector stubs
//
// Unhandled exceptions spin in a wfi loop for the moment
@@ -108,4 +108,5 @@ __vec_15:
.align 7
exception_vector_end:
");
"
);
+21 -21
View File
@@ -3,30 +3,30 @@
// Each PML4 entry references up to 512 GB of memory
// The second from the top (510) PML4 is reserved for the kernel
/// Offset of kernel (256 MiB max)
pub const KERNEL_OFFSET: usize = 0xC000_0000;
/// Offset of kernel (256 MiB max)
pub const KERNEL_OFFSET: usize = 0xC000_0000;
// Framebuffer mapped by bootloader to 0xD000_0000 (128 MiB max)
// Framebuffer mapped by bootloader to 0xD000_0000 (128 MiB max)
// Offset to APIC mappings (optional)
pub const LAPIC_OFFSET: usize = 0xD800_0000;
pub const IOAPIC_OFFSET: usize = LAPIC_OFFSET + 4096;
pub const HPET_OFFSET: usize = IOAPIC_OFFSET + 4096;
// Offset to APIC mappings (optional)
pub const LAPIC_OFFSET: usize = 0xD800_0000;
pub const IOAPIC_OFFSET: usize = LAPIC_OFFSET + 4096;
pub const HPET_OFFSET: usize = IOAPIC_OFFSET + 4096;
/// Offset to kernel heap (256 MiB max)
pub const KERNEL_HEAP_OFFSET: usize = 0xE000_0000;
/// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = rmm::MEGABYTE;
/// Offset to kernel heap (256 MiB max)
pub const KERNEL_HEAP_OFFSET: usize = 0xE000_0000;
/// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = rmm::MEGABYTE;
/// Offset to kernel percpu variables (256 MiB max)
pub const KERNEL_PERCPU_OFFSET: usize = 0xF000_0000;
/// Size of kernel percpu variables
pub const KERNEL_PERCPU_SHIFT: u8 = 16; // 2^16 = 64 KiB
pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
/// Offset to kernel percpu variables (256 MiB max)
pub const KERNEL_PERCPU_OFFSET: usize = 0xF000_0000;
/// Size of kernel percpu variables
pub const KERNEL_PERCPU_SHIFT: u8 = 16; // 2^16 = 64 KiB
pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
/// Offset of physmap (1 GiB max)
// This needs to match RMM's PHYS_OFFSET
pub const PHYS_OFFSET: usize = 0x8000_0000;
/// Offset of physmap (1 GiB max)
// This needs to match RMM's PHYS_OFFSET
pub const PHYS_OFFSET: usize = 0x8000_0000;
/// End offset of the user image, i.e. kernel start
pub const USER_END_OFFSET: usize = 0x8000_0000;
/// End offset of the user image, i.e. kernel start
pub const USER_END_OFFSET: usize = 0x8000_0000;
+12 -12
View File
@@ -3,24 +3,24 @@ use core::fmt;
use spin::Mutex;
use spin::MutexGuard;
use crate::log::{LOG, Log};
#[cfg(feature = "qemu_debug")]
use syscall::io::Io;
#[cfg(any(feature = "qemu_debug", feature = "serial_debug"))]
use crate::syscall::io::Pio;
#[cfg(feature = "lpss_debug")]
use crate::syscall::io::Mmio;
#[cfg(any(feature = "lpss_debug", feature = "serial_debug"))]
use crate::devices::uart_16550::SerialPort;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
use crate::log::{Log, LOG};
#[cfg(feature = "lpss_debug")]
use super::device::serial::LPSS;
use crate::syscall::io::Mmio;
#[cfg(any(feature = "qemu_debug", feature = "serial_debug"))]
use crate::syscall::io::Pio;
#[cfg(feature = "qemu_debug")]
use syscall::io::Io;
#[cfg(feature = "serial_debug")]
use super::device::serial::COM1;
#[cfg(feature = "lpss_debug")]
use super::device::serial::LPSS;
#[cfg(feature = "system76_ec_debug")]
use super::device::system76_ec::{SYSTEM76_EC, System76Ec};
use super::device::system76_ec::{System76Ec, SYSTEM76_EC};
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DebugDisplay, DEBUG_DISPLAY};
#[cfg(feature = "qemu_debug")]
pub static QEMU: Mutex<Pio<u8>> = Mutex::new(Pio::<u8>::new(0x402));
+234 -78
View File
@@ -28,101 +28,257 @@ pub fn cpu_info<W: Write>(w: &mut W) -> Result {
write!(w, "Features:")?;
if let Some(info) = cpuid.get_feature_info() {
if info.has_fpu() { write!(w, " fpu")? };
if info.has_vme() { write!(w, " vme")? };
if info.has_de() { write!(w, " de")? };
if info.has_pse() { write!(w, " pse")? };
if info.has_tsc() { write!(w, " tsc")? };
if info.has_msr() { write!(w, " msr")? };
if info.has_pae() { write!(w, " pae")? };
if info.has_mce() { write!(w, " mce")? };
if info.has_fpu() {
write!(w, " fpu")?
};
if info.has_vme() {
write!(w, " vme")?
};
if info.has_de() {
write!(w, " de")?
};
if info.has_pse() {
write!(w, " pse")?
};
if info.has_tsc() {
write!(w, " tsc")?
};
if info.has_msr() {
write!(w, " msr")?
};
if info.has_pae() {
write!(w, " pae")?
};
if info.has_mce() {
write!(w, " mce")?
};
if info.has_cmpxchg8b() { write!(w, " cx8")? };
if info.has_apic() { write!(w, " apic")? };
if info.has_sysenter_sysexit() { write!(w, " sep")? };
if info.has_mtrr() { write!(w, " mtrr")? };
if info.has_pge() { write!(w, " pge")? };
if info.has_mca() { write!(w, " mca")? };
if info.has_cmov() { write!(w, " cmov")? };
if info.has_pat() { write!(w, " pat")? };
if info.has_cmpxchg8b() {
write!(w, " cx8")?
};
if info.has_apic() {
write!(w, " apic")?
};
if info.has_sysenter_sysexit() {
write!(w, " sep")?
};
if info.has_mtrr() {
write!(w, " mtrr")?
};
if info.has_pge() {
write!(w, " pge")?
};
if info.has_mca() {
write!(w, " mca")?
};
if info.has_cmov() {
write!(w, " cmov")?
};
if info.has_pat() {
write!(w, " pat")?
};
if info.has_pse36() { write!(w, " pse36")? };
if info.has_psn() { write!(w, " psn")? };
if info.has_clflush() { write!(w, " clflush")? };
if info.has_ds() { write!(w, " ds")? };
if info.has_acpi() { write!(w, " acpi")? };
if info.has_mmx() { write!(w, " mmx")? };
if info.has_fxsave_fxstor() { write!(w, " fxsr")? };
if info.has_sse() { write!(w, " sse")? };
if info.has_pse36() {
write!(w, " pse36")?
};
if info.has_psn() {
write!(w, " psn")?
};
if info.has_clflush() {
write!(w, " clflush")?
};
if info.has_ds() {
write!(w, " ds")?
};
if info.has_acpi() {
write!(w, " acpi")?
};
if info.has_mmx() {
write!(w, " mmx")?
};
if info.has_fxsave_fxstor() {
write!(w, " fxsr")?
};
if info.has_sse() {
write!(w, " sse")?
};
if info.has_sse2() { write!(w, " sse2")? };
if info.has_ss() { write!(w, " ss")? };
if info.has_htt() { write!(w, " ht")? };
if info.has_tm() { write!(w, " tm")? };
if info.has_pbe() { write!(w, " pbe")? };
if info.has_sse2() {
write!(w, " sse2")?
};
if info.has_ss() {
write!(w, " ss")?
};
if info.has_htt() {
write!(w, " ht")?
};
if info.has_tm() {
write!(w, " tm")?
};
if info.has_pbe() {
write!(w, " pbe")?
};
if info.has_sse3() { write!(w, " sse3")? };
if info.has_pclmulqdq() { write!(w, " pclmulqdq")? };
if info.has_ds_area() { write!(w, " dtes64")? };
if info.has_monitor_mwait() { write!(w, " monitor")? };
if info.has_cpl() { write!(w, " ds_cpl")? };
if info.has_vmx() { write!(w, " vmx")? };
if info.has_smx() { write!(w, " smx")? };
if info.has_eist() { write!(w, " est")? };
if info.has_sse3() {
write!(w, " sse3")?
};
if info.has_pclmulqdq() {
write!(w, " pclmulqdq")?
};
if info.has_ds_area() {
write!(w, " dtes64")?
};
if info.has_monitor_mwait() {
write!(w, " monitor")?
};
if info.has_cpl() {
write!(w, " ds_cpl")?
};
if info.has_vmx() {
write!(w, " vmx")?
};
if info.has_smx() {
write!(w, " smx")?
};
if info.has_eist() {
write!(w, " est")?
};
if info.has_tm2() { write!(w, " tm2")? };
if info.has_ssse3() { write!(w, " ssse3")? };
if info.has_cnxtid() { write!(w, " cnxtid")? };
if info.has_fma() { write!(w, " fma")? };
if info.has_cmpxchg16b() { write!(w, " cx16")? };
if info.has_pdcm() { write!(w, " pdcm")? };
if info.has_pcid() { write!(w, " pcid")? };
if info.has_dca() { write!(w, " dca")? };
if info.has_tm2() {
write!(w, " tm2")?
};
if info.has_ssse3() {
write!(w, " ssse3")?
};
if info.has_cnxtid() {
write!(w, " cnxtid")?
};
if info.has_fma() {
write!(w, " fma")?
};
if info.has_cmpxchg16b() {
write!(w, " cx16")?
};
if info.has_pdcm() {
write!(w, " pdcm")?
};
if info.has_pcid() {
write!(w, " pcid")?
};
if info.has_dca() {
write!(w, " dca")?
};
if info.has_sse41() { write!(w, " sse4_1")? };
if info.has_sse42() { write!(w, " sse4_2")? };
if info.has_x2apic() { write!(w, " x2apic")? };
if info.has_movbe() { write!(w, " movbe")? };
if info.has_popcnt() { write!(w, " popcnt")? };
if info.has_tsc_deadline() { write!(w, " tsc_deadline_timer")? };
if info.has_aesni() { write!(w, " aes")? };
if info.has_xsave() { write!(w, " xsave")? };
if info.has_sse41() {
write!(w, " sse4_1")?
};
if info.has_sse42() {
write!(w, " sse4_2")?
};
if info.has_x2apic() {
write!(w, " x2apic")?
};
if info.has_movbe() {
write!(w, " movbe")?
};
if info.has_popcnt() {
write!(w, " popcnt")?
};
if info.has_tsc_deadline() {
write!(w, " tsc_deadline_timer")?
};
if info.has_aesni() {
write!(w, " aes")?
};
if info.has_xsave() {
write!(w, " xsave")?
};
if info.has_oxsave() { write!(w, " xsaveopt")? };
if info.has_avx() { write!(w, " avx")? };
if info.has_f16c() { write!(w, " f16c")? };
if info.has_rdrand() { write!(w, " rdrand")? };
if info.has_oxsave() {
write!(w, " xsaveopt")?
};
if info.has_avx() {
write!(w, " avx")?
};
if info.has_f16c() {
write!(w, " f16c")?
};
if info.has_rdrand() {
write!(w, " rdrand")?
};
}
if let Some(info) = cpuid.get_extended_processor_and_feature_identifiers() {
if info.has_64bit_mode() { write!(w, " lm")? };
if info.has_rdtscp() { write!(w, " rdtscp")? };
if info.has_1gib_pages() { write!(w, " pdpe1gb")? };
if info.has_execute_disable() { write!(w, " nx")? };
if info.has_syscall_sysret() { write!(w, " syscall")? };
if info.has_prefetchw() { write!(w, " prefetchw")? };
if info.has_lzcnt() { write!(w, " lzcnt")? };
if info.has_lahf_sahf() { write!(w, " lahf_lm")? };
if info.has_64bit_mode() {
write!(w, " lm")?
};
if info.has_rdtscp() {
write!(w, " rdtscp")?
};
if info.has_1gib_pages() {
write!(w, " pdpe1gb")?
};
if info.has_execute_disable() {
write!(w, " nx")?
};
if info.has_syscall_sysret() {
write!(w, " syscall")?
};
if info.has_prefetchw() {
write!(w, " prefetchw")?
};
if info.has_lzcnt() {
write!(w, " lzcnt")?
};
if info.has_lahf_sahf() {
write!(w, " lahf_lm")?
};
}
if let Some(info) = cpuid.get_advanced_power_mgmt_info() {
if info.has_invariant_tsc() { write!(w, " constant_tsc")? };
if info.has_invariant_tsc() {
write!(w, " constant_tsc")?
};
}
if let Some(info) = cpuid.get_extended_feature_info() {
if info.has_fsgsbase() { write!(w, " fsgsbase")? };
if info.has_tsc_adjust_msr() { write!(w, " tsc_adjust")? };
if info.has_bmi1() { write!(w, " bmi1")? };
if info.has_hle() { write!(w, " hle")? };
if info.has_avx2() { write!(w, " avx2")? };
if info.has_smep() { write!(w, " smep")? };
if info.has_bmi2() { write!(w, " bmi2")? };
if info.has_rep_movsb_stosb() { write!(w, " erms")? };
if info.has_invpcid() { write!(w, " invpcid")? };
if info.has_rtm() { write!(w, " rtm")? };
if info.has_fsgsbase() {
write!(w, " fsgsbase")?
};
if info.has_tsc_adjust_msr() {
write!(w, " tsc_adjust")?
};
if info.has_bmi1() {
write!(w, " bmi1")?
};
if info.has_hle() {
write!(w, " hle")?
};
if info.has_avx2() {
write!(w, " avx2")?
};
if info.has_smep() {
write!(w, " smep")?
};
if info.has_bmi2() {
write!(w, " bmi2")?
};
if info.has_rep_movsb_stosb() {
write!(w, " erms")?
};
if info.has_invpcid() {
write!(w, " invpcid")?
};
if info.has_rtm() {
write!(w, " rtm")?
};
//if info.has_qm() { write!(w, " qm")? };
if info.has_fpu_cs_ds_deprecated() { write!(w, " fpu_seg")? };
if info.has_mpx() { write!(w, " mpx")? };
if info.has_fpu_cs_ds_deprecated() {
write!(w, " fpu_seg")?
};
if info.has_mpx() {
write!(w, " mpx")?
};
}
writeln!(w)?;
+17 -7
View File
@@ -1,5 +1,5 @@
use crate::acpi::hpet::Hpet;
use super::pit;
use crate::acpi::hpet::Hpet;
const LEG_RT_CNF: u64 = 2;
const ENABLE_CNF: u64 = 1;
@@ -27,7 +27,8 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
{
let mut config_word = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
config_word &= !(LEG_RT_CNF | ENABLE_CNF);
hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
hpet.base_address
.write_u64(GENERAL_CONFIG_OFFSET, config_word);
}
let capability = hpet.base_address.read_u64(CAPABILITY_OFFSET);
@@ -48,9 +49,11 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
let counter = hpet.base_address.read_u64(MAIN_COUNTER_OFFSET);
let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF;
hpet.base_address.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word);
hpet.base_address
.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word);
// set accumulator value
hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, counter + divisor);
hpet.base_address
.write_u64(T0_COMPARATOR_OFFSET, counter + divisor);
// set interval
hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, divisor);
@@ -58,7 +61,8 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
{
let mut config_word: u64 = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
config_word |= LEG_RT_CNF | ENABLE_CNF;
hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
hpet.base_address
.write_u64(GENERAL_CONFIG_OFFSET, config_word);
}
println!("HPET After Init");
@@ -76,7 +80,10 @@ pub unsafe fn debug(hpet: &mut Hpet) {
println!(" clock period: {}", (capability >> 32) as u32);
println!(" ID: {:#x}", (capability >> 16) as u16);
println!(" LEG_RT_CAP: {}", capability & (1 << 15) == (1 << 15));
println!(" COUNT_SIZE_CAP: {}", capability & (1 << 13) == (1 << 13));
println!(
" COUNT_SIZE_CAP: {}",
capability & (1 << 13) == (1 << 13)
);
println!(" timers: {}", (capability >> 8) as u8 & 0x1F);
println!(" revision: {}", capability as u8);
}
@@ -92,7 +99,10 @@ pub unsafe fn debug(hpet: &mut Hpet) {
let t0_capabilities = hpet.base_address.read_u64(T0_CONFIG_CAPABILITY_OFFSET);
println!(" T0 caps: {:#x}", t0_capabilities);
println!(" interrupt routing: {:#x}", (t0_capabilities >> 32) as u32);
println!(
" interrupt routing: {:#x}",
(t0_capabilities >> 32) as u32
);
println!(" flags: {:#x}", t0_capabilities as u16);
let t0_comparator = hpet.base_address.read_u64(T0_COMPARATOR_OFFSET);
+63 -28
View File
@@ -4,15 +4,18 @@ use alloc::vec::Vec;
use spin::Mutex;
#[cfg(feature = "acpi")]
use crate::acpi::madt::{self, Madt, MadtEntry, MadtIoApic, MadtIntSrcOverride};
use crate::acpi::madt::{self, Madt, MadtEntry, MadtIntSrcOverride, MadtIoApic};
use crate::arch::interrupt::irq;
use crate::memory::Frame;
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use crate::paging::entry::EntryFlags;
use crate::{
arch::interrupt::irq,
memory::Frame,
paging::{
entry::EntryFlags, KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch,
VirtualAddress,
},
};
use super::super::cpuid::cpuid;
use super::pic;
use super::{super::cpuid::cpuid, pic};
pub struct IoApicRegs {
pointer: *const u32,
@@ -131,12 +134,12 @@ pub enum DestinationMode {
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum DeliveryMode {
Fixed = 0b000,
LowestPriority = 0b001,
Smi = 0b010,
Nmi = 0b100,
Init = 0b101,
ExtInt = 0b111,
Fixed = 0b000,
LowestPriority = 0b001,
Smi = 0b010,
Nmi = 0b100,
Init = 0b101,
ExtInt = 0b111,
}
#[derive(Clone, Copy, Debug)]
@@ -176,7 +179,9 @@ impl fmt::Debug for IoApic {
let mut guard = self.0.lock();
let count = guard.max_redirection_table_entries();
f.debug_list().entries((0..count).map(|i| guard.read_ioredtbl(i))).finish()
f.debug_list()
.entries((0..count).map(|i| guard.read_ioredtbl(i)))
.finish()
}
}
@@ -219,14 +224,10 @@ static mut IOAPICS: Option<Vec<IoApic>> = None;
static mut SRC_OVERRIDES: Option<Vec<Override>> = None;
pub fn ioapics() -> &'static [IoApic] {
unsafe {
IOAPICS.as_ref().map_or(&[], |vector| &vector[..])
}
unsafe { IOAPICS.as_ref().map_or(&[], |vector| &vector[..]) }
}
pub fn src_overrides() -> &'static [Override] {
unsafe {
SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..])
}
unsafe { SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..]) }
}
#[cfg(feature = "acpi")]
@@ -241,14 +242,24 @@ pub unsafe fn handle_ioapic(mapper: &mut KernelMapper, madt_ioapic: &'static Mad
mapper
.get_mut()
.expect("expected KernelMapper not to be locked re-entrant while mapping I/O APIC memory")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new()
.write(true)
.custom_flag(EntryFlags::NO_CACHE.bits(), true),
)
.expect("failed to map I/O APIC")
.flush();
let ioapic_registers = page.start_address().data() as *const u32;
let ioapic = IoApic::new(ioapic_registers, madt_ioapic.gsi_base);
assert_eq!(ioapic.regs.lock().id(), madt_ioapic.id, "mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC");
assert_eq!(
ioapic.regs.lock().id(),
madt_ioapic.id,
"mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC"
);
IOAPICS.get_or_insert_with(Vec::new).push(ioapic);
}
@@ -286,7 +297,11 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) {
}
pub unsafe fn init(active_table: &mut KernelMapper) {
let bsp_apic_id = cpuid().unwrap().get_feature_info().unwrap().initial_local_apic_id(); // TODO: remove unwraps
let bsp_apic_id = cpuid()
.unwrap()
.get_feature_info()
.unwrap()
.initial_local_apic_id(); // TODO: remove unwraps
// search the madt for all IOAPICs.
#[cfg(feature = "acpi")]
@@ -310,7 +325,11 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
}
}
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
println!(
"I/O APICs: {:?}, overrides: {:?}",
ioapics(),
src_overrides()
);
// map the legacy PC-compatible IRQs (0-15) to 32-47, just like we did with 8259 PIC (if it
// wouldn't have been disabled due to this I/O APIC)
@@ -318,11 +337,21 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
let (gsi, trigger_mode, polarity) = match get_override(legacy_irq) {
Some(over) => (over.gsi, over.trigger_mode, over.polarity),
None => {
if src_overrides().iter().any(|over| over.gsi == u32::from(legacy_irq) && over.bus_irq != legacy_irq) && !src_overrides().iter().any(|over| over.bus_irq == legacy_irq) {
if src_overrides()
.iter()
.any(|over| over.gsi == u32::from(legacy_irq) && over.bus_irq != legacy_irq)
&& !src_overrides()
.iter()
.any(|over| over.bus_irq == legacy_irq)
{
// there's an IRQ conflict, making this legacy IRQ inaccessible.
continue;
}
(legacy_irq.into(), TriggerMode::ConformsToSpecs, Polarity::ConformsToSpecs)
(
legacy_irq.into(),
TriggerMode::ConformsToSpecs,
Polarity::ConformsToSpecs,
)
}
};
let apic = match find_ioapic(gsi) {
@@ -354,7 +383,11 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
};
apic.map(redir_tbl_index, map_info);
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
println!(
"I/O APICs: {:?}, overrides: {:?}",
ioapics(),
src_overrides()
);
irq::set_irq_method(irq::IrqMethod::Apic);
// tell the firmware that we're using APIC rather than the default 8259 PIC.
@@ -385,7 +418,9 @@ fn resolve(irq: u8) -> u32 {
get_override(irq).map_or(u32::from(irq), |over| over.gsi)
}
fn find_ioapic(gsi: u32) -> Option<&'static IoApic> {
ioapics().iter().find(|apic| gsi >= apic.gsi_start && gsi < apic.gsi_start + u32::from(apic.count))
ioapics()
.iter()
.find(|apic| gsi >= apic.gsi_start && gsi < apic.gsi_start + u32::from(apic.count))
}
pub unsafe fn mask(irq: u8) {
+18 -14
View File
@@ -1,14 +1,16 @@
use core::sync::atomic::{self, AtomicU32};
use core::ptr::{read_volatile, write_volatile};
use core::{
ptr::{read_volatile, write_volatile},
sync::atomic::{self, AtomicU32},
};
use x86::msr::*;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags, RmmA, RmmArch, VirtualAddress};
use crate::paging::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use super::super::cpuid::cpuid;
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
x2: false,
};
pub unsafe fn init(active_table: &mut KernelMapper) {
@@ -22,7 +24,7 @@ pub unsafe fn init_ap() {
/// Local APIC
pub struct LocalApic {
pub address: usize,
pub x2: bool
pub x2: bool,
}
#[derive(Debug)]
@@ -42,19 +44,21 @@ pub fn bsp_apic_id() -> Option<u32> {
impl LocalApic {
unsafe fn init(&mut self, mapper: &mut KernelMapper) {
let mapper = mapper.get_mut().expect("expected KernelMapper not to be locked re-entrant while initializing LAPIC");
let mapper = mapper
.get_mut()
.expect("expected KernelMapper not to be locked re-entrant while initializing LAPIC");
let physaddr = PhysicalAddress::new(rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000);
let virtaddr = VirtualAddress::new(crate::LAPIC_OFFSET);
self.address = virtaddr.data();
self.x2 = cpuid().map_or(false, |cpuid| {
cpuid.get_feature_info().map_or(false, |feature_info| {
feature_info.has_x2apic()
})
cpuid
.get_feature_info()
.map_or(false, |feature_info| feature_info.has_x2apic())
});
if ! self.x2 {
if !self.x2 {
log::info!("Detected xAPIC at {:#x}", physaddr.data());
if let Some((_entry, _, flush)) = mapper.unmap_phys(virtaddr, true) {
// Unmap xAPIC page if already mapped
@@ -111,15 +115,15 @@ impl LocalApic {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_ICR) }
} else {
unsafe {
(self.read(0x310) as u64) << 32 | self.read(0x300) as u64
}
unsafe { (self.read(0x310) as u64) << 32 | self.read(0x300) as u64 }
}
}
pub fn set_icr(&mut self, value: u64) {
if self.x2 {
unsafe { wrmsr(IA32_X2APIC_ICR, value); }
unsafe {
wrmsr(IA32_X2APIC_ICR, value);
}
} else {
unsafe {
const PENDING: u32 = 1 << 12;
+6 -4
View File
@@ -1,12 +1,12 @@
pub mod cpu;
#[cfg(feature = "acpi")]
pub mod hpet;
pub mod ioapic;
pub mod local_apic;
pub mod pic;
pub mod pit;
pub mod rtc;
pub mod serial;
#[cfg(feature = "acpi")]
pub mod hpet;
#[cfg(feature = "system76_ec_debug")]
pub mod system76_ec;
@@ -16,7 +16,7 @@ pub unsafe fn init() {
pic::init();
local_apic::init(&mut KernelMapper::lock());
}
pub unsafe fn init_after_acpi() {
pub unsafe fn init_after_acpi() {
// this will disable the IOAPIC if needed.
//ioapic::init(mapper);
}
@@ -37,7 +37,9 @@ unsafe fn init_hpet() -> bool {
}
pub unsafe fn init_noncore() {
if false /*TODO: init_hpet()*/ {
if false
/*TODO: init_hpet()*/
{
log::info!("HPET used as system timer");
} else {
pit::init();
+4 -2
View File
@@ -1,5 +1,7 @@
use crate::syscall::io::{Io, Pio};
use crate::arch::interrupt::irq;
use crate::{
arch::interrupt::irq,
syscall::io::{Io, Pio},
};
pub static mut MASTER: Pic = Pic::new(0x20);
pub static mut SLAVE: Pic = Pic::new(0xA0);
+4 -2
View File
@@ -1,5 +1,7 @@
use crate::syscall::io::{Io, Pio};
use crate::time;
use crate::{
syscall::io::{Io, Pio},
time,
};
pub fn init() {
let mut rtc = Rtc::new();
+13 -9
View File
@@ -1,7 +1,6 @@
use crate::devices::uart_16550::SerialPort;
#[cfg(feature = "lpss_debug")]
use crate::syscall::io::Mmio;
use crate::syscall::io::Pio;
use crate::{devices::uart_16550::SerialPort, syscall::io::Pio};
use spin::Mutex;
pub static COM1: Mutex<SerialPort<Pio<u8>>> = Mutex::new(SerialPort::<Pio<u8>>::new(0x3F8));
@@ -22,19 +21,24 @@ pub unsafe fn init() {
let address = crate::PHYS_OFFSET + 0xFE032000;
{
use crate::paging::{ActivePageTable, Page, VirtualAddress, entry::EntryFlags};
use crate::memory::{Frame, PhysicalAddress};
use crate::{
memory::{Frame, PhysicalAddress},
paging::{entry::EntryFlags, ActivePageTable, Page, VirtualAddress},
};
let mut active_table = ActivePageTable::new();
let page = Page::containing_address(VirtualAddress::new(address));
let frame = Frame::containing_address(PhysicalAddress::new(address - crate::PHYS_OFFSET));
let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE);
let frame =
Frame::containing_address(PhysicalAddress::new(address - crate::PHYS_OFFSET));
let result = active_table.map_to(
page,
frame,
EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE,
);
result.flush(&mut active_table);
}
let lpss = SerialPort::<Mmio<u32>>::new(
crate::PHYS_OFFSET + 0xFE032000
);
let lpss = SerialPort::<Mmio<u32>>::new(crate::PHYS_OFFSET + 0xFE032000);
lpss.init();
*LPSS.lock() = Some(lpss);
+1 -3
View File
@@ -13,9 +13,7 @@ pub struct System76Ec {
impl System76Ec {
pub fn new() -> Option<Self> {
let mut system76_ec = Self {
base: 0x0E00,
};
let mut system76_ec = Self { base: 0x0E00 };
if system76_ec.probe() {
Some(system76_ec)
} else {
+69 -25
View File
@@ -1,16 +1,15 @@
//! Global descriptor table
use core::convert::TryInto;
use core::mem;
use core::ptr::addr_of_mut;
use core::{convert::TryInto, mem, ptr::addr_of_mut};
use crate::LogicalCpuId;
use x86::bits32::task::TaskStateSegment;
use x86::Ring;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector};
use x86::task;
use x86::{
bits32::task::TaskStateSegment,
dtables::{self, DescriptorTablePointer},
segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector},
task, Ring,
};
use crate::paging::{RmmA, RmmArch, PAGE_SIZE};
@@ -48,28 +47,73 @@ static INIT_GDT: [GdtEntry; 3] = [
// Null
GdtEntry::new(0, 0, 0, 0),
// Kernel code
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// Kernel data
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
];
const BASE_GDT: [GdtEntry; 9] = [
// Null
GdtEntry::new(0, 0, 0, 0),
// Kernel code
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// Kernel data
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// Kernel TLS
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// User (32-bit) code
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// User data
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// User FS (for TLS)
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// User GS (for TLS)
GdtEntry::new(0, 0xFFFFF, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0xFFFFF,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_PAGE_SIZE | GDT_F_PROTECTED_MODE,
),
// TSS
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0),
];
@@ -96,9 +140,10 @@ pub unsafe fn pcr() -> *mut ProcessorControlRegion {
#[cfg(feature = "pti")]
pub unsafe fn set_tss_stack(stack: usize) {
use super::pti::{PTI_CPU_STACK, PTI_CONTEXT_STACK};
use super::pti::{PTI_CONTEXT_STACK, PTI_CPU_STACK};
addr_of_mut!((*pcr()).tss.0.ss0).write((GDT_KERNEL_DATA << 3) as u16);
addr_of_mut!((*pcr()).tss.0.esp0).write((PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()) as u32);
addr_of_mut!((*pcr()).tss.0.esp0)
.write((PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()) as u32);
PTI_CONTEXT_STACK = stack;
}
@@ -128,7 +173,8 @@ pub unsafe fn init() {
/// Initialize GDT and configure percpu.
pub unsafe fn init_paging(stack_offset: usize, cpu_id: LogicalCpuId) {
let pcr_frame = crate::memory::allocate_frames(1).expect("failed to allocate PCR frame");
let pcr = &mut *(RmmA::phys_to_virt(pcr_frame.start_address()).data() as *mut ProcessorControlRegion);
let pcr =
&mut *(RmmA::phys_to_virt(pcr_frame.start_address()).data() as *mut ProcessorControlRegion);
pcr.self_ref = pcr as *const _ as usize;
pcr.gdt = BASE_GDT;
@@ -179,7 +225,7 @@ pub struct GdtEntry {
pub offsetm: u8,
pub access: u8,
pub flags_limith: u8,
pub offseth: u8
pub offseth: u8,
}
impl GdtEntry {
@@ -190,14 +236,12 @@ impl GdtEntry {
offsetm: (offset >> 16) as u8,
access,
flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F,
offseth: (offset >> 24) as u8
offseth: (offset >> 24) as u8,
}
}
pub fn offset(&self) -> u32 {
(self.offsetl as u32) |
((self.offsetm as u32) << 16) |
((self.offseth as u32) << 24)
(self.offsetl as u32) | ((self.offsetm as u32) << 16) | ((self.offseth as u32) << 24)
}
pub fn set_offset(&mut self, offset: u32) {
+55 -19
View File
@@ -1,21 +1,24 @@
use core::num::NonZeroU8;
use core::sync::atomic::{AtomicU32, Ordering};
use core::mem;
use core::{
mem,
num::NonZeroU8,
sync::atomic::{AtomicU32, Ordering},
};
use alloc::boxed::Box;
use hashbrown::HashMap;
use x86::segmentation::Descriptor as X86IdtEntry;
use x86::dtables::{self, DescriptorTablePointer};
use x86::{
dtables::{self, DescriptorTablePointer},
segmentation::Descriptor as X86IdtEntry,
};
use crate::{interrupt::*, LogicalCpuId};
use crate::ipi::IpiKind;
use crate::{interrupt::*, ipi::IpiKind, LogicalCpuId};
use spin::RwLock;
pub static mut INIT_IDTR: DescriptorTablePointer<X86IdtEntry> = DescriptorTablePointer {
limit: 0,
base: 0 as *const X86IdtEntry
base: 0 as *const X86IdtEntry,
};
pub type IdtEntries = [IdtEntry; 256];
@@ -46,7 +49,8 @@ impl Idt {
let byte_index = index / 32;
let bit = index % 32;
{ &self.reservations[usize::from(byte_index)] }.fetch_or(u32::from(reserved) << bit, Ordering::AcqRel);
{ &self.reservations[usize::from(byte_index)] }
.fetch_or(u32::from(reserved) << bit, Ordering::AcqRel);
}
#[inline]
pub fn is_reserved_mut(&mut self, index: u8) -> bool {
@@ -61,7 +65,8 @@ impl Idt {
let byte_index = index / 32;
let bit = index % 32;
*{ &mut self.reservations[usize::from(byte_index)] }.get_mut() |= u32::from(reserved) << bit;
*{ &mut self.reservations[usize::from(byte_index)] }.get_mut() |=
u32::from(reserved) << bit;
}
}
@@ -75,7 +80,18 @@ pub fn is_reserved(cpu_id: LogicalCpuId, index: u8) -> bool {
let byte_index = index / 32;
let bit = index % 32;
{ &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.load(Ordering::Acquire) & (1 << bit) != 0
{
&IDTS
.read()
.as_ref()
.unwrap()
.get(&cpu_id)
.unwrap()
.reservations[usize::from(byte_index)]
}
.load(Ordering::Acquire)
& (1 << bit)
!= 0
}
#[inline]
@@ -83,13 +99,22 @@ pub fn set_reserved(cpu_id: LogicalCpuId, index: u8, reserved: bool) {
let byte_index = index / 32;
let bit = index % 32;
{ &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.fetch_or(u32::from(reserved) << bit, Ordering::AcqRel);
{
&IDTS
.read()
.as_ref()
.unwrap()
.get(&cpu_id)
.unwrap()
.reservations[usize::from(byte_index)]
}
.fetch_or(u32::from(reserved) << bit, Ordering::AcqRel);
}
pub fn allocate_interrupt() -> Option<NonZeroU8> {
let cpu_id = crate::cpu_id();
for number in 50..=254 {
if ! is_reserved(cpu_id, number) {
if !is_reserved(cpu_id, number) {
set_reserved(cpu_id, number, true);
return Some(unsafe { NonZeroU8::new_unchecked(number) });
}
@@ -120,8 +145,14 @@ pub unsafe fn init() {
const fn new_idt_reservations() -> [AtomicU32; 8] {
[
AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0),
AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0)
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
AtomicU32::new(0),
]
}
@@ -133,7 +164,9 @@ pub unsafe fn init_paging_post_heap(is_bsp: bool, cpu_id: LogicalCpuId) {
if is_bsp {
idts_btree.insert(cpu_id, &mut INIT_BSP_IDT);
} else {
let idt = idts_btree.entry(cpu_id).or_insert_with(|| Box::leak(Box::new(Idt::new())));
let idt = idts_btree
.entry(cpu_id)
.or_insert_with(|| Box::leak(Box::new(Idt::new())));
init_generic(is_bsp, idt);
}
}
@@ -238,7 +271,6 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) {
current_idt[48].set_func(irq::lapic_timer);
current_idt[49].set_func(irq::lapic_error);
// reserve bits 49:32, which are for the standard IRQs, and for the local apic timer and error.
*current_reservations[1].get_mut() |= 0x0003_FFFF;
} else {
@@ -309,7 +341,11 @@ impl IdtEntry {
}
pub fn set_ist(&mut self, ist: u8) {
assert_eq!(ist & 0x07, ist, "interrupt stack table must be within 0..=7");
assert_eq!(
ist & 0x07,
ist,
"interrupt stack table must be within 0..=7"
);
self.zero &= 0xF8;
self.zero |= ist;
}
@@ -321,7 +357,7 @@ impl IdtEntry {
}
// A function to set the offset more easily
pub fn set_func(&mut self, func: unsafe extern fn()) {
pub fn set_func(&mut self, func: unsafe extern "C" fn()) {
self.set_flags(IdtFlags::PRESENT | IdtFlags::RING_0 | IdtFlags::INTERRUPT);
self.set_offset((crate::gdt::GDT_KERNEL_CODE as u16) << 3, func as usize);
}
+23 -14
View File
@@ -1,18 +1,12 @@
use rmm::TableKind;
use x86::irq::PageFaultError;
use crate::memory::GenericPfFlags;
use crate::paging::VirtualAddress;
use crate::{
interrupt::stack_trace,
ptrace,
syscall::flag::*,
interrupt_stack,
interrupt_error,
interrupt::stack_trace, interrupt_error, interrupt_stack, memory::GenericPfFlags,
paging::VirtualAddress, ptrace, syscall::flag::*,
};
extern {
extern "C" {
fn ksignal(signal: usize);
}
@@ -140,11 +134,26 @@ interrupt_error!(page, |stack| {
let arch_flags = PageFaultError::from_bits_truncate(stack.code as u32);
let mut generic_flags = GenericPfFlags::empty();
generic_flags.set(GenericPfFlags::PRESENT, arch_flags.contains(PageFaultError::P));
generic_flags.set(GenericPfFlags::INVOLVED_WRITE, arch_flags.contains(PageFaultError::WR));
generic_flags.set(GenericPfFlags::USER_NOT_SUPERVISOR, arch_flags.contains(PageFaultError::US));
generic_flags.set(GenericPfFlags::INVL, arch_flags.contains(PageFaultError::RSVD));
generic_flags.set(GenericPfFlags::INSTR_NOT_DATA, arch_flags.contains(PageFaultError::ID));
generic_flags.set(
GenericPfFlags::PRESENT,
arch_flags.contains(PageFaultError::P),
);
generic_flags.set(
GenericPfFlags::INVOLVED_WRITE,
arch_flags.contains(PageFaultError::WR),
);
generic_flags.set(
GenericPfFlags::USER_NOT_SUPERVISOR,
arch_flags.contains(PageFaultError::US),
);
generic_flags.set(
GenericPfFlags::INVL,
arch_flags.contains(PageFaultError::RSVD),
);
generic_flags.set(
GenericPfFlags::INSTR_NOT_DATA,
arch_flags.contains(PageFaultError::ID),
);
if crate::memory::page_fault_handler(&mut stack.inner, generic_flags, cr2).is_err() {
println!("Page fault: {:>08X} {:#?}", cr2.data(), arch_flags);
+31 -18
View File
@@ -1,7 +1,6 @@
use core::mem;
use crate::memory::ArchIntCtx;
use crate::syscall::IntRegisters;
use crate::{memory::ArchIntCtx, syscall::IntRegisters};
use super::super::flags::*;
@@ -50,9 +49,8 @@ pub struct IretRegisters {
// The following will only be present if interrupt is raised from another
// privilege ring. Otherwise, they are undefined values.
// ----
pub esp: usize,
pub ss: usize
pub ss: usize,
}
impl IretRegisters {
@@ -169,61 +167,73 @@ impl InterruptErrorStack {
#[macro_export]
macro_rules! push_scratch {
() => { "
() => {
"
// Push scratch registers (minus eax)
push ecx
push edx
" };
"
};
}
#[macro_export]
macro_rules! pop_scratch {
() => { "
() => {
"
// Pop scratch registers
pop edx
pop ecx
pop eax
" };
"
};
}
#[macro_export]
macro_rules! push_preserved {
() => { "
() => {
"
// Push preserved registers
push ebx
push edi
push esi
push ebp
" };
"
};
}
#[macro_export]
macro_rules! pop_preserved {
() => { "
() => {
"
// Pop preserved registers
pop ebp
pop esi
pop edi
pop ebx
" };
"
};
}
// Must always happen after push_scratch
macro_rules! enter_gs {
() => { "
() => {
"
// Enter kernel GS segment
mov ecx, gs
push ecx
mov ecx, 0x18
mov gs, ecx
" }
"
};
}
// Must always happen before pop_scratch
macro_rules! exit_gs {
() => { "
() => {
"
// Exit kernel GS segment
pop ecx
mov gs, ecx
" }
"
};
}
#[macro_export]
@@ -411,13 +421,16 @@ macro_rules! interrupt_error {
}
#[naked]
unsafe extern "C" fn usercopy_trampoline() {
core::arch::asm!("
core::arch::asm!(
"
pop esi
pop edi
mov eax, 1
ret
", options(noreturn));
",
options(noreturn)
);
}
impl ArchIntCtx for InterruptStack {
+1 -2
View File
@@ -1,7 +1,6 @@
use x86::tlb;
use crate::context;
use crate::device::local_apic::LOCAL_APIC;
use crate::{context, device::local_apic::LOCAL_APIC};
interrupt!(wakeup, || {
LOCAL_APIC.eoi();
+43 -17
View File
@@ -2,14 +2,21 @@ use core::sync::atomic::{AtomicUsize, Ordering};
use alloc::vec::Vec;
use crate::{interrupt, interrupt_stack};
use crate::context::timeout;
use crate::device::{local_apic, ioapic, pic, pit};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::{debug_input, debug_notify};
use crate::scheme::serio::serio_input;
use crate::{context, time};
use crate::{
context,
context::timeout,
device::{
ioapic, local_apic, pic, pit,
serial::{COM1, COM2},
},
interrupt, interrupt_stack,
ipi::{ipi, IpiKind, IpiTarget},
scheme::{
debug::{debug_input, debug_notify},
serio::serio_input,
},
time,
};
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -33,9 +40,13 @@ pub fn spurious_count() -> usize {
pub fn spurious_irq_resource() -> syscall::Result<Vec<u8>> {
match irq_method() {
IrqMethod::Apic => Ok(Vec::from(&b"(not implemented for APIC yet)"[..])),
IrqMethod::Pic => {
Ok(format!("{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n", spurious_count_irq7(), spurious_count_irq15(), spurious_count()).into_bytes())
}
IrqMethod::Pic => Ok(format!(
"{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n",
spurious_count_irq7(),
spurious_count_irq15(),
spurious_count()
)
.into_bytes()),
}
}
@@ -55,7 +66,7 @@ fn irq_method() -> IrqMethod {
}
}
extern {
extern "C" {
// triggers irq scheme
fn irq_trigger(irq: u8);
}
@@ -64,7 +75,11 @@ extern {
/// scheme user unmasks it ("acknowledges" it).
unsafe fn trigger(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_mask(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_mask(irq)
}
}
IrqMethod::Apic => ioapic_mask(irq),
}
irq_trigger(irq);
@@ -74,7 +89,11 @@ unsafe fn trigger(irq: u8) {
/// processed the IRQ.
pub unsafe fn acknowledge(irq: usize) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_unmask(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_unmask(irq)
}
}
IrqMethod::Apic => ioapic_unmask(irq),
}
}
@@ -82,7 +101,11 @@ pub unsafe fn acknowledge(irq: usize) {
/// Sends an end-of-interrupt, so that the interrupt controller can go on to the next one.
pub unsafe fn eoi(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_eoi(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_eoi(irq)
}
}
IrqMethod::Apic => lapic_eoi(),
}
}
@@ -242,7 +265,7 @@ interrupt!(ata2, || {
if irq_method() == IrqMethod::Pic && pic::SLAVE.isr() & (1 << 7) == 0 {
SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed);
pic::MASTER.ack();
return
return;
}
trigger(15);
eoi(15);
@@ -254,7 +277,10 @@ interrupt!(lapic_timer, || {
});
interrupt!(lapic_error, || {
println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr());
println!(
"Local apic internal error: ESR={:#0x}",
local_apic::LOCAL_APIC.esr()
);
lapic_eoi();
});
+8 -5
View File
@@ -9,11 +9,12 @@ pub mod irq;
pub mod syscall;
pub mod trace;
pub use self::handler::InterruptStack;
pub use self::trace::stack_trace;
pub use self::{handler::InterruptStack, trace::stack_trace};
pub use super::idt::{available_irqs_iter, is_reserved, set_reserved};
pub use super::device::local_apic::bsp_apic_id;
pub use super::{
device::local_apic::bsp_apic_id,
idt::{available_irqs_iter, is_reserved, set_reserved},
};
/// Clear interrupts
#[inline(always)]
@@ -53,5 +54,7 @@ pub unsafe fn halt() {
/// Safe because it is similar to a NOP, and has no memory effects
#[inline(always)]
pub fn pause() {
unsafe { core::arch::asm!("pause", options(nomem, nostack)); }
unsafe {
core::arch::asm!("pause", options(nomem, nostack));
}
}
+31 -22
View File
@@ -1,9 +1,7 @@
use crate::{
arch::{gdt, interrupt::InterruptStack},
context,
ptrace,
syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL},
context, ptrace, syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_POST_SYSCALL, PTRACE_STOP_PRE_SYSCALL},
};
use core::mem::offset_of;
use x86::{bits32::task::TaskStateSegment, msr, segmentation::SegmentSelector};
@@ -25,33 +23,44 @@ macro_rules! with_interrupt_stack {
}
ptrace::breakpoint_callback(PTRACE_STOP_POST_SYSCALL, None);
}}
}};
}
interrupt_stack!(syscall, |stack| {
with_interrupt_stack!(|stack| {
let scratch = &stack.scratch;
let preserved = &stack.preserved;
syscall::syscall(scratch.eax, preserved.ebx, scratch.ecx, scratch.edx, preserved.esi, preserved.edi, stack)
syscall::syscall(
scratch.eax,
preserved.ebx,
scratch.ecx,
scratch.edx,
preserved.esi,
preserved.edi,
stack,
)
})
});
#[naked]
pub unsafe extern "C" fn clone_ret() {
core::arch::asm!(concat!(
// The address of this instruction is injected by `clone` in process.rs, on
// top of the stack syscall->inner in this file, which is done using the ebp
// register we save there.
//
// The top of our stack here is the address pointed to by ebp, which is:
//
// - the previous ebp
// - the return location
//
// Our goal is to return from the parent function, inner, so we restore
// ebp...
"pop ebp\n",
// ...and we return to the address at the top of the stack
"ret\n",
), options(noreturn));
core::arch::asm!(
concat!(
// The address of this instruction is injected by `clone` in process.rs, on
// top of the stack syscall->inner in this file, which is done using the ebp
// register we save there.
//
// The top of our stack here is the address pointed to by ebp, which is:
//
// - the previous ebp
// - the return location
//
// Our goal is to return from the parent function, inner, so we restore
// ebp...
"pop ebp\n",
// ...and we return to the address at the top of the stack
"ret\n",
),
options(noreturn)
);
}
+14 -9
View File
@@ -3,7 +3,7 @@ use core::{mem, str};
use goblin::elf::sym;
use rustc_demangle::demangle;
use crate::{paging::{KernelMapper, VirtualAddress}};
use crate::paging::{KernelMapper, VirtualAddress};
/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing
@@ -45,11 +45,12 @@ pub unsafe fn stack_trace() {
//TODO: Do not create Elf object for every symbol lookup
#[inline(never)]
pub unsafe fn symbol_trace(addr: usize) {
use core::slice;
use core::sync::atomic::Ordering;
use core::{slice, sync::atomic::Ordering};
use crate::elf::Elf;
use crate::start::{KERNEL_BASE, KERNEL_SIZE};
use crate::{
elf::Elf,
start::{KERNEL_BASE, KERNEL_SIZE},
};
let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::PHYS_OFFSET) as *const u8;
let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));
@@ -65,10 +66,14 @@ pub unsafe fn symbol_trace(addr: usize) {
if let Some(symbols) = elf.symbols() {
for sym in symbols {
if sym::st_type(sym.st_info) == sym::STT_FUNC
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
{
println!(" {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize);
println!(
" {:>016X}+{:>04X}",
sym.st_value,
addr - sym.st_value as usize
);
if let Some(strtab) = strtab_opt {
let start = strtab.sh_offset as usize + sym.st_name as usize;
@@ -82,7 +87,7 @@ pub unsafe fn symbol_trace(addr: usize) {
}
if end > start {
let sym_slice = &elf.data[start .. end - 1];
let sym_slice = &elf.data[start..end - 1];
if let Ok(sym_name) = str::from_utf8(sym_slice) {
println!(" {:#}", demangle(sym_name));
}
+11 -5
View File
@@ -42,9 +42,9 @@ pub mod stop;
pub mod time;
pub use ::rmm::X86Arch as CurrentRmmArch;
use crate::{memory::PAGE_SIZE, Bootstrap};
use ::rmm::Arch;
use crate::{Bootstrap, memory::PAGE_SIZE};
pub use ::rmm::X86Arch as CurrentRmmArch;
// Flags
pub mod flags {
@@ -56,7 +56,8 @@ pub mod flags {
#[naked]
#[link_section = ".usercopy-fns"]
pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -> u8 {
core::arch::asm!("
core::arch::asm!(
"
push edi
push esi
@@ -70,12 +71,17 @@ pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -
xor eax, eax
ret
", options(noreturn));
",
options(noreturn)
);
}
pub use arch_copy_to_user as arch_copy_from_user;
pub unsafe fn bootstrap_mem(bootstrap: &Bootstrap) -> &'static [u8] {
core::slice::from_raw_parts(CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8, bootstrap.page_count * PAGE_SIZE)
core::slice::from_raw_parts(
CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8,
bootstrap.page_count * PAGE_SIZE,
)
}
pub const KFX_SIZE: usize = 512;
+9 -3
View File
@@ -4,16 +4,22 @@ use super::RmmA;
pub use rmm::{Flusher, PageFlush, PageFlushAll};
pub struct InactiveFlusher { _inner: () }
pub struct InactiveFlusher {
_inner: (),
}
impl InactiveFlusher {
// TODO: cpu id
pub fn new() -> Self { Self { _inner: () } }
pub fn new() -> Self {
Self { _inner: () }
}
}
impl Flusher<RmmA> for InactiveFlusher {
fn consume(&mut self, flush: PageFlush<RmmA>) {
// TODO: Push to TLB "mailbox" or tell it to reload CR3 if there are too many entries.
unsafe { flush.ignore(); }
unsafe {
flush.ignore();
}
}
}
impl Drop for InactiveFlusher {
+5 -9
View File
@@ -6,15 +6,8 @@ use x86::msr;
use self::mapper::PageFlushAll;
pub use rmm::{
Arch as RmmArch,
Flusher,
PageFlags,
PhysicalAddress,
TableKind,
VirtualAddress,
};
pub use super::CurrentRmmArch as RmmA;
pub use rmm::{Arch as RmmArch, Flusher, PageFlags, PhysicalAddress, TableKind, VirtualAddress};
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
pub use crate::rmm::KernelMapper;
@@ -111,7 +104,10 @@ impl Page {
}
pub fn range_inclusive(start: Page, r#final: Page) -> PageIter {
PageIter { start, end: r#final.next() }
PageIter {
start,
end: r#final.next(),
}
}
pub fn range_exclusive(start: Page, end: Page) -> PageIter {
PageIter { start, end }
+11 -9
View File
@@ -4,9 +4,9 @@ use core::ptr;
#[cfg(feature = "pti")]
use crate::memory::Frame;
#[cfg(feature = "pti")]
use crate::paging::ActivePageTable;
#[cfg(feature = "pti")]
use crate::paging::entry::EntryFlags;
#[cfg(feature = "pti")]
use crate::paging::ActivePageTable;
#[cfg(feature = "pti")]
#[thread_local]
@@ -26,11 +26,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
let new_rsp = new - offset_rsp;
ptr::copy_nonoverlapping(
old_rsp as *const u8,
new_rsp as *mut u8,
offset_rsp
);
ptr::copy_nonoverlapping(old_rsp as *const u8, new_rsp as *mut u8, offset_rsp);
asm!("", out("rsp") new_rsp);
}
@@ -53,14 +49,20 @@ 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,
);
}
#[cfg(feature = "pti")]
#[inline(always)]
pub unsafe extern "C" 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() };
+163 -94
View File
@@ -1,26 +1,12 @@
use core::{
cell::SyncUnsafeCell,
cmp,
mem,
slice,
cmp, mem, slice,
sync::atomic::{self, AtomicUsize, Ordering},
};
use rmm::{
KILOBYTE,
Arch, BuddyAllocator, BumpAllocator, FrameAllocator, FrameCount, FrameUsage, MemoryArea,
PageEntry, PageFlags, PageMapper, PhysicalAddress, TableKind, VirtualAddress, KILOBYTE,
MEGABYTE,
Arch,
BuddyAllocator,
BumpAllocator,
FrameAllocator,
FrameCount,
FrameUsage,
MemoryArea,
PageEntry,
PageFlags,
PageMapper,
PhysicalAddress,
TableKind,
VirtualAddress,
};
use spin::Mutex;
@@ -65,11 +51,16 @@ unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> PageFlags<A> {
unsafe fn inner<A: Arch>(
areas: &'static [MemoryArea],
kernel_base: usize, kernel_size_aligned: usize,
stack_base: usize, stack_size_aligned: usize,
env_base: usize, env_size_aligned: usize,
acpi_base: usize, acpi_size_aligned: usize,
initfs_base: usize, initfs_size_aligned: usize,
kernel_base: usize,
kernel_size_aligned: usize,
stack_base: usize,
stack_size_aligned: usize,
env_base: usize,
env_size_aligned: usize,
acpi_base: usize,
acpi_size_aligned: usize,
initfs_base: usize,
initfs_size_aligned: usize,
) -> BuddyAllocator<A> {
// First, calculate how much memory we have
let mut size = 0;
@@ -86,17 +77,20 @@ unsafe fn inner<A: Arch>(
let mut bump_allocator = BumpAllocator::<A>::new(areas, 0);
{
let mut mapper = PageMapper::<A, _>::create(
TableKind::Kernel,
&mut bump_allocator
).expect("failed to create Mapper");
let mut mapper = PageMapper::<A, _>::create(TableKind::Kernel, &mut bump_allocator)
.expect("failed to create Mapper");
// Pre-allocate all kernel PD entries so that when the page table is copied,
// these entries are synced between processes
for i in 512..1024 {
let phys = mapper.allocator_mut().allocate_one().expect("failed to map page table");
let phys = mapper
.allocator_mut()
.allocate_one()
.expect("failed to map page table");
let flags = A::ENTRY_FLAG_READWRITE | A::ENTRY_FLAG_DEFAULT_TABLE;
mapper.table().set_entry(i, PageEntry::new(phys.data() | flags));
mapper
.table()
.set_entry(i, PageEntry::new(phys.data() | flags));
}
// Map all physical areas at PHYS_OFFSET
@@ -105,11 +99,9 @@ unsafe fn inner<A: Arch>(
let phys = area.base.add(i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -119,19 +111,15 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(kernel_base + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(crate::KERNEL_OFFSET + i * A::PAGE_SIZE);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
let virt = A::phys_to_virt(phys);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
@@ -141,11 +129,9 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
};
@@ -158,8 +144,8 @@ unsafe fn inner<A: Arch>(
// Ensure graphical debug region remains paged
#[cfg(feature = "graphical_debug")]
{
use crate::devices::graphical_debug::FRAMEBUFFER;
use super::paging::entry::EntryFlags;
use crate::devices::graphical_debug::FRAMEBUFFER;
let (phys, virt, size) = *FRAMEBUFFER.lock();
@@ -167,14 +153,13 @@ unsafe fn inner<A: Arch>(
for i in 0..pages {
let phys = PhysicalAddress::new(phys + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(virt + i * A::PAGE_SIZE);
let flags = PageFlags::new().write(true)
let flags = PageFlags::new()
.write(true)
// Write combining flag
.custom_flag(EntryFlags::HUGE_PAGE.bits(), true);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -194,7 +179,10 @@ unsafe fn inner<A: Arch>(
// Create the physical memory map
let offset = bump_allocator.offset();
log::info!("Permanently used: {} KB", (offset + (KILOBYTE - 1)) / KILOBYTE);
log::info!(
"Permanently used: {} KB",
(offset + (KILOBYTE - 1)) / KILOBYTE
);
BuddyAllocator::<A>::new(bump_allocator).expect("failed to create BuddyAllocator")
}
@@ -238,10 +226,12 @@ impl core::fmt::Debug for LockedAllocator {
}
}
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new([MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512]);
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new(
[MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512],
);
static AREA_COUNT: SyncUnsafeCell<u16> = SyncUnsafeCell::new(0);
pub fn areas() -> &'static [MemoryArea] {
@@ -271,7 +261,12 @@ pub struct KernelMapper {
impl KernelMapper {
fn lock_inner(current_processor: usize) -> bool {
loop {
match LOCK_OWNER.compare_exchange_weak(NO_PROCESSOR, current_processor, Ordering::Acquire, Ordering::Relaxed) {
match LOCK_OWNER.compare_exchange_weak(
NO_PROCESSOR,
current_processor,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => break,
// already owned by this hardware thread
Err(id) if id == current_processor => break,
@@ -285,15 +280,20 @@ impl KernelMapper {
prev_count > 0
}
pub unsafe fn lock_for_manual_mapper(current_processor: LogicalCpuId, mapper: crate::paging::PageMapper) -> Self {
pub unsafe fn lock_for_manual_mapper(
current_processor: LogicalCpuId,
mapper: crate::paging::PageMapper,
) -> Self {
let ro = Self::lock_inner(current_processor.get() as usize);
Self {
mapper,
ro,
}
Self { mapper, ro }
}
pub fn lock_manually(current_processor: LogicalCpuId) -> Self {
unsafe { Self::lock_for_manual_mapper(current_processor, PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR)) }
unsafe {
Self::lock_for_manual_mapper(
current_processor,
PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR),
)
}
}
pub fn lock() -> Self {
Self::lock_manually(crate::cpu_id())
@@ -328,12 +328,18 @@ impl Drop for KernelMapper {
}
pub unsafe fn init(
kernel_base: usize, kernel_size: usize,
stack_base: usize, stack_size: usize,
env_base: usize, env_size: usize,
acpi_base: usize, acpi_size: usize,
areas_base: usize, areas_size: usize,
initfs_base: usize, initfs_size: usize,
kernel_base: usize,
kernel_size: usize,
stack_base: usize,
stack_size: usize,
env_base: usize,
env_size: usize,
acpi_base: usize,
acpi_size: usize,
areas_base: usize,
areas_size: usize,
initfs_base: usize,
initfs_size: usize,
) {
type A = RmmA;
@@ -341,26 +347,26 @@ pub unsafe fn init(
let real_size = 0x100000;
let real_end = real_base + real_size;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_end = kernel_base + kernel_size_aligned;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_end = stack_base + stack_size_aligned;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let env_end = env_base + env_size_aligned;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_end = acpi_base + acpi_size_aligned;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_end = initfs_base + initfs_size_aligned;
let areas = &mut *AREAS.get();
let bootloader_areas = slice::from_raw_parts(
areas_base as *const BootloaderMemoryEntry,
areas_size / mem::size_of::<BootloaderMemoryEntry>()
areas_size / mem::size_of::<BootloaderMemoryEntry>(),
);
// Copy memory map from bootloader location, and page align it
@@ -393,44 +399,86 @@ pub unsafe fn init(
// Ensure real-mode areas are not used
if base < real_end && base + size > real_base {
log::warn!("{:X}:{:X} overlaps with real mode {:X}:{:X}", base, size, real_base, real_size);
log::warn!(
"{:X}:{:X} overlaps with real mode {:X}:{:X}",
base,
size,
real_base,
real_size
);
new_base = cmp::max(new_base, real_end);
}
// Ensure kernel areas are not used
if base < kernel_end && base + size > kernel_base {
log::warn!("{:X}:{:X} overlaps with kernel {:X}:{:X}", base, size, kernel_base, kernel_size);
log::warn!(
"{:X}:{:X} overlaps with kernel {:X}:{:X}",
base,
size,
kernel_base,
kernel_size
);
new_base = cmp::max(new_base, kernel_end);
}
// Ensure stack areas are not used
if base < stack_end && base + size > stack_base {
log::warn!("{:X}:{:X} overlaps with stack {:X}:{:X}", base, size, stack_base, stack_size);
log::warn!(
"{:X}:{:X} overlaps with stack {:X}:{:X}",
base,
size,
stack_base,
stack_size
);
new_base = cmp::max(new_base, stack_end);
}
// Ensure env areas are not used
if base < env_end && base + size > env_base {
log::warn!("{:X}:{:X} overlaps with env {:X}:{:X}", base, size, env_base, env_size);
log::warn!(
"{:X}:{:X} overlaps with env {:X}:{:X}",
base,
size,
env_base,
env_size
);
new_base = cmp::max(new_base, env_end);
}
// Ensure acpi areas are not used
if base < acpi_end && base + size > acpi_base {
log::warn!("{:X}:{:X} overlaps with acpi {:X}:{:X}", base, size, acpi_base, acpi_size);
log::warn!(
"{:X}:{:X} overlaps with acpi {:X}:{:X}",
base,
size,
acpi_base,
acpi_size
);
new_base = cmp::max(new_base, acpi_end);
}
// Ensure initfs areas are not used
if base < initfs_end && base + size > initfs_base {
log::warn!("{:X}:{:X} overlaps with initfs {:X}:{:X}", base, size, initfs_base, initfs_size);
log::warn!(
"{:X}:{:X} overlaps with initfs {:X}:{:X}",
base,
size,
initfs_base,
initfs_size
);
new_base = cmp::max(new_base, initfs_end);
}
if new_base != base {
let end = base + size;
let new_size = end.checked_sub(new_base).unwrap_or(0);
log::info!("{:X}:{:X} moved to {:X}:{:X}", base, size, new_base, new_size);
log::info!(
"{:X}:{:X} moved to {:X}:{:X}",
base,
size,
new_base,
new_size
);
base = new_base;
size = new_size;
}
@@ -443,7 +491,13 @@ pub unsafe fn init(
size = 0; // Skip area
} else if base + size > physmap_size {
let new_size = physmap_size.checked_sub(base).unwrap_or(0);
log::warn!("{:X}:{:X} outside of physmap, moved to {:X}:{:X}", base, size, base, new_size);
log::warn!(
"{:X}:{:X} outside of physmap, moved to {:X}:{:X}",
base,
size,
base,
new_size
);
size = new_size;
}
@@ -454,8 +508,18 @@ pub unsafe fn init(
let other_end = other_base + other.size;
if base < other_end && base + size > other_base {
let new_base = cmp::min(base, other_base);
let new_size = cmp::max(base + size, other_end).checked_sub(new_base).unwrap_or(0);
log::warn!("{:X}:{:X} overlaps with area {:X}:{:X}, combining into {:X}:{:X}", base, size, other_base, other.size, new_base, new_size);
let new_size = cmp::max(base + size, other_end)
.checked_sub(new_base)
.unwrap_or(0);
log::warn!(
"{:X}:{:X} overlaps with area {:X}:{:X}, combining into {:X}:{:X}",
base,
size,
other_base,
other.size,
new_base,
new_size
);
areas[other_i].base = PhysicalAddress::new(new_base);
areas[other_i].size = new_size;
size = 0; // Skip area
@@ -475,11 +539,16 @@ pub unsafe fn init(
let allocator = inner::<A>(
areas,
kernel_base, kernel_size_aligned,
stack_base, stack_size_aligned,
env_base, env_size_aligned,
acpi_base, acpi_size_aligned,
initfs_base, initfs_size_aligned,
kernel_base,
kernel_size_aligned,
stack_base,
stack_size_aligned,
env_base,
env_size_aligned,
acpi_base,
acpi_size_aligned,
initfs_base,
initfs_size_aligned,
);
*INNER_ALLOCATOR.lock() = Some(allocator);
}
+70 -31
View File
@@ -2,24 +2,22 @@
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, AtomicU32};
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
use crate::{allocator, LogicalCpuId};
#[cfg(feature = "acpi")]
use crate::acpi;
use crate::arch::pti;
use crate::arch::flags::*;
use crate::device;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug;
use crate::gdt;
use crate::idt;
use crate::interrupt;
use crate::log::{self, info};
use crate::memory;
use crate::paging::{self, KernelMapper, PhysicalAddress, RmmA, RmmArch, TableKind};
use crate::{
allocator,
arch::{flags::*, pti},
device, gdt, idt, interrupt,
log::{self, info},
memory,
paging::{self, KernelMapper, PhysicalAddress, RmmA, RmmArch, TableKind},
LogicalCpuId,
};
/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
@@ -68,7 +66,7 @@ pub struct KernelArgs {
/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
let bootstrap = {
let args = args_ptr.read();
@@ -82,7 +80,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
KERNEL_SIZE.store(args.kernel_size as usize, Ordering::SeqCst);
// Convert env to slice
let env = slice::from_raw_parts((args.env_base as usize + crate::PHYS_OFFSET) as *const u8, args.env_size as usize);
let env = slice::from_raw_parts(
(args.env_base as usize + crate::PHYS_OFFSET) as *const u8,
args.env_size as usize,
);
// Set up graphical debug
#[cfg(feature = "graphical_debug")]
@@ -104,12 +105,36 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
});
info!("Redox OS starting...");
info!("Kernel: {:X}:{:X}", { args.kernel_base }, { args.kernel_base } + { args.kernel_size });
info!("Stack: {:X}:{:X}", { args.stack_base }, { args.stack_base } + { args.stack_size });
info!("Env: {:X}:{:X}", { args.env_base }, { args.env_base } + { args.env_size });
info!("RSDPs: {:X}:{:X}", { args.acpi_rsdps_base }, { args.acpi_rsdps_base } + { args.acpi_rsdps_size });
info!("Areas: {:X}:{:X}", { args.areas_base }, { args.areas_base } + { args.areas_size });
info!("Bootstrap: {:X}:{:X}", { args.bootstrap_base }, { args.bootstrap_base } + { args.bootstrap_size });
info!(
"Kernel: {:X}:{:X}",
{ args.kernel_base },
{ args.kernel_base } + { args.kernel_size }
);
info!(
"Stack: {:X}:{:X}",
{ args.stack_base },
{ args.stack_base } + { args.stack_size }
);
info!(
"Env: {:X}:{:X}",
{ args.env_base },
{ args.env_base } + { args.env_size }
);
info!(
"RSDPs: {:X}:{:X}",
{ args.acpi_rsdps_base },
{ args.acpi_rsdps_base } + { args.acpi_rsdps_size }
);
info!(
"Areas: {:X}:{:X}",
{ args.areas_base },
{ args.areas_base } + { args.areas_size }
);
info!(
"Bootstrap: {:X}:{:X}",
{ args.bootstrap_base },
{ args.bootstrap_base } + { args.bootstrap_size }
);
info!("Bootstrap entry point: {:X}", { args.bootstrap_entry });
// Set up GDT before paging
@@ -120,18 +145,27 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Initialize RMM
crate::arch::rmm::init(
args.kernel_base as usize, args.kernel_size as usize,
args.stack_base as usize, args.stack_size as usize,
args.env_base as usize, args.env_size as usize,
args.acpi_rsdps_base as usize, args.acpi_rsdps_size as usize,
args.areas_base as usize, args.areas_size as usize,
args.bootstrap_base as usize, args.bootstrap_size as usize,
args.kernel_base as usize,
args.kernel_size as usize,
args.stack_base as usize,
args.stack_size as usize,
args.env_base as usize,
args.env_size as usize,
args.acpi_rsdps_base as usize,
args.acpi_rsdps_size as usize,
args.areas_base as usize,
args.areas_size as usize,
args.bootstrap_base as usize,
args.bootstrap_size as usize,
);
// Initialize paging
paging::init();
// Set up GDT after paging with TLS
gdt::init_paging(args.stack_base as usize + args.stack_size as usize, LogicalCpuId::BSP);
gdt::init_paging(
args.stack_base as usize + args.stack_size as usize,
LogicalCpuId::BSP,
);
// Set up IDT
idt::init_paging_bsp();
@@ -163,7 +197,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
#[cfg(feature = "acpi")]
{
acpi::init(if args.acpi_rsdps_base != 0 && args.acpi_rsdps_size > 0 {
Some(((args.acpi_rsdps_base as usize + crate::PHYS_OFFSET) as u64, args.acpi_rsdps_size as u64))
Some((
(args.acpi_rsdps_base as usize + crate::PHYS_OFFSET) as u64,
args.acpi_rsdps_size as u64,
))
} else {
None
});
@@ -183,7 +220,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
BSP_READY.store(true, Ordering::SeqCst);
crate::Bootstrap {
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(args.bootstrap_base as usize)),
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(
args.bootstrap_base as usize,
)),
page_count: (args.bootstrap_size as usize) / crate::memory::PAGE_SIZE,
entry: args.bootstrap_entry as usize,
env,
@@ -202,7 +241,7 @@ pub struct KernelArgsAp {
}
/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
pub unsafe extern "C" fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
let cpu_id = {
let args = &*args_ptr;
let cpu_id = LogicalCpuId::new(args.cpu_id as u32);
@@ -240,7 +279,7 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
cpu_id
};
while ! BSP_READY.load(Ordering::SeqCst) {
while !BSP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
+9 -10
View File
@@ -1,14 +1,10 @@
#[cfg(feature = "acpi")]
use crate::{
context,
scheme::acpi,
time,
};
use crate::{context, scheme::acpi, time};
use crate::syscall::io::{Io, Pio};
#[no_mangle]
pub unsafe extern fn kreset() -> ! {
pub unsafe extern "C" fn kreset() -> ! {
println!("kreset");
// 8042 reset
@@ -24,11 +20,14 @@ pub unsafe extern fn kreset() -> ! {
pub unsafe fn emergency_reset() -> ! {
// Use triple fault to guarantee reset
core::arch::asm!("
core::arch::asm!(
"
cli
lidt cs:0
int $3
", options(noreturn));
",
options(noreturn)
);
}
#[cfg(feature = "acpi")]
@@ -36,7 +35,7 @@ fn userspace_acpi_shutdown() {
log::info!("Notifying any potential ACPI driver");
// Tell whatever driver that handles ACPI, that it should enter the S5 state (i.e.
// shutdown).
if ! acpi::register_kstop() {
if !acpi::register_kstop() {
// There was no context to switch to.
log::info!("No ACPI driver was alive to handle shutdown.");
return;
@@ -63,7 +62,7 @@ fn userspace_acpi_shutdown() {
}
#[no_mangle]
pub unsafe extern fn kstop() -> ! {
pub unsafe extern "C" fn kstop() -> ! {
log::info!("Running kstop()");
#[cfg(feature = "acpi")]
+55 -18
View File
@@ -5,9 +5,11 @@ use core::mem::size_of;
use spin::Once;
use x86::controlregs::{Cr4, Xcr0};
use crate::context::memory::PageSpan;
use crate::cpuid::{has_ext_feat, cpuid_always, feature_info};
use crate::paging::{KernelMapper, Page, PageFlags, PAGE_SIZE, VirtualAddress};
use crate::{
context::memory::PageSpan,
cpuid::{cpuid_always, feature_info, has_ext_feat},
paging::{KernelMapper, Page, PageFlags, VirtualAddress, PAGE_SIZE},
};
#[cfg(all(cpu_feature_never = "xsave", not(cpu_feature_never = "xsaveopt")))]
compile_error!("cannot force-disable xsave without force-disabling xsaveopt");
@@ -31,7 +33,10 @@ pub unsafe fn early_init(bsp: bool) {
let relocs_size = crate::kernel_executable_offsets::__altrelocs_end() - relocs_offset;
assert_eq!(relocs_size % size_of::<AltReloc>(), 0);
let relocs = core::slice::from_raw_parts(relocs_offset as *const AltReloc, relocs_size / size_of::<AltReloc>());
let relocs = core::slice::from_raw_parts(
relocs_offset as *const AltReloc,
relocs_size / size_of::<AltReloc>(),
);
let mut enable = KcpuFeatures::empty();
@@ -62,12 +67,16 @@ pub unsafe fn early_init(bsp: bool) {
#[cfg(not(cpu_feature_never = "xsave"))]
if feature_info().has_xsave() {
use raw_cpuid::{ExtendedRegisterType, ExtendedRegisterStateLocation};
use raw_cpuid::{ExtendedRegisterStateLocation, ExtendedRegisterType};
x86::controlregs::cr4_write(x86::controlregs::cr4() | x86::controlregs::Cr4::CR4_ENABLE_OS_XSAVE);
x86::controlregs::cr4_write(
x86::controlregs::cr4() | x86::controlregs::Cr4::CR4_ENABLE_OS_XSAVE,
);
let mut xcr0 = Xcr0::XCR0_FPU_MMX_STATE | Xcr0::XCR0_SSE_STATE;
let ext_state_info = cpuid_always().get_extended_state_info().expect("must be present if XSAVE is supported");
let ext_state_info = cpuid_always()
.get_extended_state_info()
.expect("must be present if XSAVE is supported");
enable |= KcpuFeatures::XSAVE;
enable.set(KcpuFeatures::XSAVEOPT, ext_state_info.has_xsaveopt());
@@ -77,10 +86,13 @@ pub unsafe fn early_init(bsp: bool) {
xcr0 |= Xcr0::XCR0_AVX_STATE;
x86::controlregs::xcr0_write(xcr0);
let state = ext_state_info.iter().find(|state| {
state.register() == ExtendedRegisterType::Avx
&& state.location() == ExtendedRegisterStateLocation::Xcr0
}).expect("CPUID said AVX was supported but there's no state info");
let state = ext_state_info
.iter()
.find(|state| {
state.register() == ExtendedRegisterType::Avx
&& state.location() == ExtendedRegisterStateLocation::Xcr0
})
.expect("CPUID said AVX was supported but there's no state info");
if state.size() as usize != 16 * core::mem::size_of::<u128>() {
log::warn!("Unusual AVX state size {}", state.size());
@@ -123,20 +135,37 @@ pub unsafe fn early_init(bsp: bool) {
unsafe fn overwrite(relocs: &[AltReloc], enable: KcpuFeatures) {
let mut mapper = KernelMapper::lock();
for reloc in relocs.iter().copied() {
let name = core::str::from_utf8(core::slice::from_raw_parts(reloc.name_start, reloc.name_len)).expect("invalid feature name");
let name = core::str::from_utf8(core::slice::from_raw_parts(
reloc.name_start,
reloc.name_len,
))
.expect("invalid feature name");
let altcode = core::slice::from_raw_parts(reloc.altcode_start, reloc.altcode_len);
let dst_pages = PageSpan::between(
Page::containing_address(VirtualAddress::new(reloc.code_start as usize)),
Page::containing_address(VirtualAddress::new((reloc.code_start as usize + reloc.origcode_len).next_multiple_of(PAGE_SIZE))),
Page::containing_address(VirtualAddress::new(
(reloc.code_start as usize + reloc.origcode_len).next_multiple_of(PAGE_SIZE),
)),
);
for page in dst_pages.pages() {
mapper.remap(page.start_address(), PageFlags::new().write(true).execute(true).global(true)).unwrap().flush();
mapper
.remap(
page.start_address(),
PageFlags::new().write(true).execute(true).global(true),
)
.unwrap()
.flush();
}
let code = core::slice::from_raw_parts_mut(reloc.code_start, reloc.padded_len);
log::trace!("feature {} current {:x?} altcode {:x?}", name, code, altcode);
log::trace!(
"feature {} current {:x?} altcode {:x?}",
name,
code,
altcode
);
let feature_is_enabled = match name {
"smap" => enable.contains(KcpuFeatures::SMAP),
@@ -170,7 +199,9 @@ unsafe fn overwrite(relocs: &[AltReloc], enable: KcpuFeatures) {
&[0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[
0x66, 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
],
];
for chunk in dst_nops.chunks_mut(NOPS_TABLE.len()) {
@@ -179,7 +210,13 @@ unsafe fn overwrite(relocs: &[AltReloc], enable: KcpuFeatures) {
log::trace!("feature {} new {:x?} altcode {:x?}", name, code, altcode);
for page in dst_pages.pages() {
mapper.remap(page.start_address(), PageFlags::new().write(false).execute(true).global(true)).unwrap().flush();
mapper
.remap(
page.start_address(),
PageFlags::new().write(false).execute(true).global(true),
)
.unwrap()
.flush();
}
}
}
@@ -208,7 +245,7 @@ mod xsave {
pub ymm_upper_offset: Option<u32>,
pub xsave_size: u32,
}
pub(in super) static XSAVE_INFO: Once<XsaveInfo> = Once::new();
pub(super) static XSAVE_INFO: Once<XsaveInfo> = Once::new();
pub fn info() -> Option<&'static XsaveInfo> {
XSAVE_INFO.get()
+3 -3
View File
@@ -15,18 +15,18 @@ pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;
/// Offset of kernel
pub const KERNEL_MAX_SIZE: usize = 1_usize << 31;
pub const KERNEL_OFFSET: usize = KERNEL_MAX_SIZE.wrapping_neg();
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK) / PML4_SIZE;
/// Offset to kernel heap
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK) / PML4_SIZE;
/// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
/// Offset of physmap
// This needs to match RMM's PHYS_OFFSET
pub const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK) / PML4_SIZE;
/// End offset of the user image, i.e. kernel start
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
+3 -1
View File
@@ -17,7 +17,9 @@ pub fn cpuid_always() -> CpuId {
}
pub fn feature_info() -> FeatureInfo {
cpuid_always().get_feature_info().expect("x86_64 requires CPUID leaf=0x01 to be present")
cpuid_always()
.get_feature_info()
.expect("x86_64 requires CPUID leaf=0x01 to be present")
}
pub fn has_ext_feat(feat: impl FnOnce(ExtendedFeatures) -> bool) -> bool {
+12 -12
View File
@@ -3,24 +3,24 @@ use core::fmt;
use spin::Mutex;
use spin::MutexGuard;
use crate::log::{LOG, Log};
#[cfg(feature = "qemu_debug")]
use syscall::io::Io;
#[cfg(any(feature = "qemu_debug", feature = "serial_debug"))]
use crate::syscall::io::Pio;
#[cfg(feature = "lpss_debug")]
use crate::syscall::io::Mmio;
#[cfg(any(feature = "lpss_debug", feature = "serial_debug"))]
use crate::devices::uart_16550::SerialPort;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
use crate::log::{Log, LOG};
#[cfg(feature = "lpss_debug")]
use super::device::serial::LPSS;
use crate::syscall::io::Mmio;
#[cfg(any(feature = "qemu_debug", feature = "serial_debug"))]
use crate::syscall::io::Pio;
#[cfg(feature = "qemu_debug")]
use syscall::io::Io;
#[cfg(feature = "serial_debug")]
use super::device::serial::COM1;
#[cfg(feature = "lpss_debug")]
use super::device::serial::LPSS;
#[cfg(feature = "system76_ec_debug")]
use super::device::system76_ec::{SYSTEM76_EC, System76Ec};
use super::device::system76_ec::{System76Ec, SYSTEM76_EC};
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug::{DebugDisplay, DEBUG_DISPLAY};
#[cfg(feature = "qemu_debug")]
pub static QEMU: Mutex<Pio<u8>> = Mutex::new(Pio::<u8>::new(0x402));
+234 -78
View File
@@ -28,101 +28,257 @@ pub fn cpu_info<W: Write>(w: &mut W) -> Result {
write!(w, "Features:")?;
if let Some(info) = cpuid.get_feature_info() {
if info.has_fpu() { write!(w, " fpu")? };
if info.has_vme() { write!(w, " vme")? };
if info.has_de() { write!(w, " de")? };
if info.has_pse() { write!(w, " pse")? };
if info.has_tsc() { write!(w, " tsc")? };
if info.has_msr() { write!(w, " msr")? };
if info.has_pae() { write!(w, " pae")? };
if info.has_mce() { write!(w, " mce")? };
if info.has_fpu() {
write!(w, " fpu")?
};
if info.has_vme() {
write!(w, " vme")?
};
if info.has_de() {
write!(w, " de")?
};
if info.has_pse() {
write!(w, " pse")?
};
if info.has_tsc() {
write!(w, " tsc")?
};
if info.has_msr() {
write!(w, " msr")?
};
if info.has_pae() {
write!(w, " pae")?
};
if info.has_mce() {
write!(w, " mce")?
};
if info.has_cmpxchg8b() { write!(w, " cx8")? };
if info.has_apic() { write!(w, " apic")? };
if info.has_sysenter_sysexit() { write!(w, " sep")? };
if info.has_mtrr() { write!(w, " mtrr")? };
if info.has_pge() { write!(w, " pge")? };
if info.has_mca() { write!(w, " mca")? };
if info.has_cmov() { write!(w, " cmov")? };
if info.has_pat() { write!(w, " pat")? };
if info.has_cmpxchg8b() {
write!(w, " cx8")?
};
if info.has_apic() {
write!(w, " apic")?
};
if info.has_sysenter_sysexit() {
write!(w, " sep")?
};
if info.has_mtrr() {
write!(w, " mtrr")?
};
if info.has_pge() {
write!(w, " pge")?
};
if info.has_mca() {
write!(w, " mca")?
};
if info.has_cmov() {
write!(w, " cmov")?
};
if info.has_pat() {
write!(w, " pat")?
};
if info.has_pse36() { write!(w, " pse36")? };
if info.has_psn() { write!(w, " psn")? };
if info.has_clflush() { write!(w, " clflush")? };
if info.has_ds() { write!(w, " ds")? };
if info.has_acpi() { write!(w, " acpi")? };
if info.has_mmx() { write!(w, " mmx")? };
if info.has_fxsave_fxstor() { write!(w, " fxsr")? };
if info.has_sse() { write!(w, " sse")? };
if info.has_pse36() {
write!(w, " pse36")?
};
if info.has_psn() {
write!(w, " psn")?
};
if info.has_clflush() {
write!(w, " clflush")?
};
if info.has_ds() {
write!(w, " ds")?
};
if info.has_acpi() {
write!(w, " acpi")?
};
if info.has_mmx() {
write!(w, " mmx")?
};
if info.has_fxsave_fxstor() {
write!(w, " fxsr")?
};
if info.has_sse() {
write!(w, " sse")?
};
if info.has_sse2() { write!(w, " sse2")? };
if info.has_ss() { write!(w, " ss")? };
if info.has_htt() { write!(w, " ht")? };
if info.has_tm() { write!(w, " tm")? };
if info.has_pbe() { write!(w, " pbe")? };
if info.has_sse2() {
write!(w, " sse2")?
};
if info.has_ss() {
write!(w, " ss")?
};
if info.has_htt() {
write!(w, " ht")?
};
if info.has_tm() {
write!(w, " tm")?
};
if info.has_pbe() {
write!(w, " pbe")?
};
if info.has_sse3() { write!(w, " sse3")? };
if info.has_pclmulqdq() { write!(w, " pclmulqdq")? };
if info.has_ds_area() { write!(w, " dtes64")? };
if info.has_monitor_mwait() { write!(w, " monitor")? };
if info.has_cpl() { write!(w, " ds_cpl")? };
if info.has_vmx() { write!(w, " vmx")? };
if info.has_smx() { write!(w, " smx")? };
if info.has_eist() { write!(w, " est")? };
if info.has_sse3() {
write!(w, " sse3")?
};
if info.has_pclmulqdq() {
write!(w, " pclmulqdq")?
};
if info.has_ds_area() {
write!(w, " dtes64")?
};
if info.has_monitor_mwait() {
write!(w, " monitor")?
};
if info.has_cpl() {
write!(w, " ds_cpl")?
};
if info.has_vmx() {
write!(w, " vmx")?
};
if info.has_smx() {
write!(w, " smx")?
};
if info.has_eist() {
write!(w, " est")?
};
if info.has_tm2() { write!(w, " tm2")? };
if info.has_ssse3() { write!(w, " ssse3")? };
if info.has_cnxtid() { write!(w, " cnxtid")? };
if info.has_fma() { write!(w, " fma")? };
if info.has_cmpxchg16b() { write!(w, " cx16")? };
if info.has_pdcm() { write!(w, " pdcm")? };
if info.has_pcid() { write!(w, " pcid")? };
if info.has_dca() { write!(w, " dca")? };
if info.has_tm2() {
write!(w, " tm2")?
};
if info.has_ssse3() {
write!(w, " ssse3")?
};
if info.has_cnxtid() {
write!(w, " cnxtid")?
};
if info.has_fma() {
write!(w, " fma")?
};
if info.has_cmpxchg16b() {
write!(w, " cx16")?
};
if info.has_pdcm() {
write!(w, " pdcm")?
};
if info.has_pcid() {
write!(w, " pcid")?
};
if info.has_dca() {
write!(w, " dca")?
};
if info.has_sse41() { write!(w, " sse4_1")? };
if info.has_sse42() { write!(w, " sse4_2")? };
if info.has_x2apic() { write!(w, " x2apic")? };
if info.has_movbe() { write!(w, " movbe")? };
if info.has_popcnt() { write!(w, " popcnt")? };
if info.has_tsc_deadline() { write!(w, " tsc_deadline_timer")? };
if info.has_aesni() { write!(w, " aes")? };
if info.has_xsave() { write!(w, " xsave")? };
if info.has_sse41() {
write!(w, " sse4_1")?
};
if info.has_sse42() {
write!(w, " sse4_2")?
};
if info.has_x2apic() {
write!(w, " x2apic")?
};
if info.has_movbe() {
write!(w, " movbe")?
};
if info.has_popcnt() {
write!(w, " popcnt")?
};
if info.has_tsc_deadline() {
write!(w, " tsc_deadline_timer")?
};
if info.has_aesni() {
write!(w, " aes")?
};
if info.has_xsave() {
write!(w, " xsave")?
};
if info.has_oxsave() { write!(w, " xsaveopt")? };
if info.has_avx() { write!(w, " avx")? };
if info.has_f16c() { write!(w, " f16c")? };
if info.has_rdrand() { write!(w, " rdrand")? };
if info.has_oxsave() {
write!(w, " xsaveopt")?
};
if info.has_avx() {
write!(w, " avx")?
};
if info.has_f16c() {
write!(w, " f16c")?
};
if info.has_rdrand() {
write!(w, " rdrand")?
};
}
if let Some(info) = cpuid.get_extended_processor_and_feature_identifiers() {
if info.has_64bit_mode() { write!(w, " lm")? };
if info.has_rdtscp() { write!(w, " rdtscp")? };
if info.has_1gib_pages() { write!(w, " pdpe1gb")? };
if info.has_execute_disable() { write!(w, " nx")? };
if info.has_syscall_sysret() { write!(w, " syscall")? };
if info.has_prefetchw() { write!(w, " prefetchw")? };
if info.has_lzcnt() { write!(w, " lzcnt")? };
if info.has_lahf_sahf() { write!(w, " lahf_lm")? };
if info.has_64bit_mode() {
write!(w, " lm")?
};
if info.has_rdtscp() {
write!(w, " rdtscp")?
};
if info.has_1gib_pages() {
write!(w, " pdpe1gb")?
};
if info.has_execute_disable() {
write!(w, " nx")?
};
if info.has_syscall_sysret() {
write!(w, " syscall")?
};
if info.has_prefetchw() {
write!(w, " prefetchw")?
};
if info.has_lzcnt() {
write!(w, " lzcnt")?
};
if info.has_lahf_sahf() {
write!(w, " lahf_lm")?
};
}
if let Some(info) = cpuid.get_advanced_power_mgmt_info() {
if info.has_invariant_tsc() { write!(w, " constant_tsc")? };
if info.has_invariant_tsc() {
write!(w, " constant_tsc")?
};
}
if let Some(info) = cpuid.get_extended_feature_info() {
if info.has_fsgsbase() { write!(w, " fsgsbase")? };
if info.has_tsc_adjust_msr() { write!(w, " tsc_adjust")? };
if info.has_bmi1() { write!(w, " bmi1")? };
if info.has_hle() { write!(w, " hle")? };
if info.has_avx2() { write!(w, " avx2")? };
if info.has_smep() { write!(w, " smep")? };
if info.has_bmi2() { write!(w, " bmi2")? };
if info.has_rep_movsb_stosb() { write!(w, " erms")? };
if info.has_invpcid() { write!(w, " invpcid")? };
if info.has_rtm() { write!(w, " rtm")? };
if info.has_fsgsbase() {
write!(w, " fsgsbase")?
};
if info.has_tsc_adjust_msr() {
write!(w, " tsc_adjust")?
};
if info.has_bmi1() {
write!(w, " bmi1")?
};
if info.has_hle() {
write!(w, " hle")?
};
if info.has_avx2() {
write!(w, " avx2")?
};
if info.has_smep() {
write!(w, " smep")?
};
if info.has_bmi2() {
write!(w, " bmi2")?
};
if info.has_rep_movsb_stosb() {
write!(w, " erms")?
};
if info.has_invpcid() {
write!(w, " invpcid")?
};
if info.has_rtm() {
write!(w, " rtm")?
};
//if info.has_qm() { write!(w, " qm")? };
if info.has_fpu_cs_ds_deprecated() { write!(w, " fpu_seg")? };
if info.has_mpx() { write!(w, " mpx")? };
if info.has_fpu_cs_ds_deprecated() {
write!(w, " fpu_seg")?
};
if info.has_mpx() {
write!(w, " mpx")?
};
}
writeln!(w)?;
+17 -7
View File
@@ -1,5 +1,5 @@
use crate::acpi::hpet::Hpet;
use super::pit;
use crate::acpi::hpet::Hpet;
const LEG_RT_CNF: u64 = 2;
const ENABLE_CNF: u64 = 1;
@@ -27,7 +27,8 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
{
let mut config_word = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
config_word &= !(LEG_RT_CNF | ENABLE_CNF);
hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
hpet.base_address
.write_u64(GENERAL_CONFIG_OFFSET, config_word);
}
let capability = hpet.base_address.read_u64(CAPABILITY_OFFSET);
@@ -48,9 +49,11 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
let counter = hpet.base_address.read_u64(MAIN_COUNTER_OFFSET);
let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF;
hpet.base_address.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word);
hpet.base_address
.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word);
// set accumulator value
hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, counter + divisor);
hpet.base_address
.write_u64(T0_COMPARATOR_OFFSET, counter + divisor);
// set interval
hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, divisor);
@@ -58,7 +61,8 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
{
let mut config_word: u64 = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET);
config_word |= LEG_RT_CNF | ENABLE_CNF;
hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, config_word);
hpet.base_address
.write_u64(GENERAL_CONFIG_OFFSET, config_word);
}
println!("HPET After Init");
@@ -76,7 +80,10 @@ pub unsafe fn debug(hpet: &mut Hpet) {
println!(" clock period: {}", (capability >> 32) as u32);
println!(" ID: {:#x}", (capability >> 16) as u16);
println!(" LEG_RT_CAP: {}", capability & (1 << 15) == (1 << 15));
println!(" COUNT_SIZE_CAP: {}", capability & (1 << 13) == (1 << 13));
println!(
" COUNT_SIZE_CAP: {}",
capability & (1 << 13) == (1 << 13)
);
println!(" timers: {}", (capability >> 8) as u8 & 0x1F);
println!(" revision: {}", capability as u8);
}
@@ -92,7 +99,10 @@ pub unsafe fn debug(hpet: &mut Hpet) {
let t0_capabilities = hpet.base_address.read_u64(T0_CONFIG_CAPABILITY_OFFSET);
println!(" T0 caps: {:#x}", t0_capabilities);
println!(" interrupt routing: {:#x}", (t0_capabilities >> 32) as u32);
println!(
" interrupt routing: {:#x}",
(t0_capabilities >> 32) as u32
);
println!(" flags: {:#x}", t0_capabilities as u16);
let t0_comparator = hpet.base_address.read_u64(T0_COMPARATOR_OFFSET);
+60 -28
View File
@@ -4,15 +4,15 @@ use alloc::vec::Vec;
use spin::Mutex;
#[cfg(feature = "acpi")]
use crate::acpi::madt::{self, Madt, MadtEntry, MadtIoApic, MadtIntSrcOverride};
use crate::acpi::madt::{self, Madt, MadtEntry, MadtIntSrcOverride, MadtIoApic};
use crate::arch::interrupt::irq;
use crate::memory::Frame;
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch};
use crate::paging::entry::EntryFlags;
use crate::{
arch::interrupt::irq,
memory::Frame,
paging::{entry::EntryFlags, KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch},
};
use super::super::cpuid::cpuid;
use super::pic;
use super::{super::cpuid::cpuid, pic};
pub struct IoApicRegs {
pointer: *const u32,
@@ -131,12 +131,12 @@ pub enum DestinationMode {
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum DeliveryMode {
Fixed = 0b000,
LowestPriority = 0b001,
Smi = 0b010,
Nmi = 0b100,
Init = 0b101,
ExtInt = 0b111,
Fixed = 0b000,
LowestPriority = 0b001,
Smi = 0b010,
Nmi = 0b100,
Init = 0b101,
ExtInt = 0b111,
}
#[derive(Clone, Copy, Debug)]
@@ -176,7 +176,9 @@ impl fmt::Debug for IoApic {
let mut guard = self.0.lock();
let count = guard.max_redirection_table_entries();
f.debug_list().entries((0..count).map(|i| guard.read_ioredtbl(i))).finish()
f.debug_list()
.entries((0..count).map(|i| guard.read_ioredtbl(i)))
.finish()
}
}
@@ -219,14 +221,10 @@ static mut IOAPICS: Option<Vec<IoApic>> = None;
static mut SRC_OVERRIDES: Option<Vec<Override>> = None;
pub fn ioapics() -> &'static [IoApic] {
unsafe {
IOAPICS.as_ref().map_or(&[], |vector| &vector[..])
}
unsafe { IOAPICS.as_ref().map_or(&[], |vector| &vector[..]) }
}
pub fn src_overrides() -> &'static [Override] {
unsafe {
SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..])
}
unsafe { SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..]) }
}
#[cfg(feature = "acpi")]
@@ -241,14 +239,24 @@ pub unsafe fn handle_ioapic(mapper: &mut KernelMapper, madt_ioapic: &'static Mad
mapper
.get_mut()
.expect("expected KernelMapper not to be locked re-entrant while mapping I/O APIC memory")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.map_phys(
page.start_address(),
frame.start_address(),
PageFlags::new()
.write(true)
.custom_flag(EntryFlags::NO_CACHE.bits(), true),
)
.expect("failed to map I/O APIC")
.flush();
let ioapic_registers = page.start_address().data() as *const u32;
let ioapic = IoApic::new(ioapic_registers, madt_ioapic.gsi_base);
assert_eq!(ioapic.regs.lock().id(), madt_ioapic.id, "mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC");
assert_eq!(
ioapic.regs.lock().id(),
madt_ioapic.id,
"mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC"
);
IOAPICS.get_or_insert_with(Vec::new).push(ioapic);
}
@@ -286,7 +294,11 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) {
}
pub unsafe fn init(active_table: &mut KernelMapper) {
let bsp_apic_id = cpuid().unwrap().get_feature_info().unwrap().initial_local_apic_id(); // TODO: remove unwraps
let bsp_apic_id = cpuid()
.unwrap()
.get_feature_info()
.unwrap()
.initial_local_apic_id(); // TODO: remove unwraps
// search the madt for all IOAPICs.
#[cfg(feature = "acpi")]
@@ -310,7 +322,11 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
}
}
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
println!(
"I/O APICs: {:?}, overrides: {:?}",
ioapics(),
src_overrides()
);
// map the legacy PC-compatible IRQs (0-15) to 32-47, just like we did with 8259 PIC (if it
// wouldn't have been disabled due to this I/O APIC)
@@ -318,11 +334,21 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
let (gsi, trigger_mode, polarity) = match get_override(legacy_irq) {
Some(over) => (over.gsi, over.trigger_mode, over.polarity),
None => {
if src_overrides().iter().any(|over| over.gsi == u32::from(legacy_irq) && over.bus_irq != legacy_irq) && !src_overrides().iter().any(|over| over.bus_irq == legacy_irq) {
if src_overrides()
.iter()
.any(|over| over.gsi == u32::from(legacy_irq) && over.bus_irq != legacy_irq)
&& !src_overrides()
.iter()
.any(|over| over.bus_irq == legacy_irq)
{
// there's an IRQ conflict, making this legacy IRQ inaccessible.
continue;
}
(legacy_irq.into(), TriggerMode::ConformsToSpecs, Polarity::ConformsToSpecs)
(
legacy_irq.into(),
TriggerMode::ConformsToSpecs,
Polarity::ConformsToSpecs,
)
}
};
let apic = match find_ioapic(gsi) {
@@ -354,7 +380,11 @@ pub unsafe fn init(active_table: &mut KernelMapper) {
};
apic.map(redir_tbl_index, map_info);
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
println!(
"I/O APICs: {:?}, overrides: {:?}",
ioapics(),
src_overrides()
);
irq::set_irq_method(irq::IrqMethod::Apic);
// tell the firmware that we're using APIC rather than the default 8259 PIC.
@@ -385,7 +415,9 @@ fn resolve(irq: u8) -> u32 {
get_override(irq).map_or(u32::from(irq), |over| over.gsi)
}
fn find_ioapic(gsi: u32) -> Option<&'static IoApic> {
ioapics().iter().find(|apic| gsi >= apic.gsi_start && gsi < apic.gsi_start + u32::from(apic.count))
ioapics()
.iter()
.find(|apic| gsi >= apic.gsi_start && gsi < apic.gsi_start + u32::from(apic.count))
}
pub unsafe fn mask(irq: u8) {
+18 -14
View File
@@ -1,14 +1,16 @@
use core::sync::atomic::{self, AtomicU64};
use core::ptr::{read_volatile, write_volatile};
use core::{
ptr::{read_volatile, write_volatile},
sync::atomic::{self, AtomicU64},
};
use x86::msr::*;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags, RmmA, RmmArch};
use crate::paging::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch};
use super::super::cpuid::cpuid;
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
x2: false,
};
pub unsafe fn init(active_table: &mut KernelMapper) {
@@ -22,7 +24,7 @@ pub unsafe fn init_ap() {
/// Local APIC
pub struct LocalApic {
pub address: usize,
pub x2: bool
pub x2: bool,
}
#[derive(Debug)]
@@ -42,19 +44,21 @@ pub fn bsp_apic_id() -> Option<u32> {
impl LocalApic {
unsafe fn init(&mut self, mapper: &mut KernelMapper) {
let mapper = mapper.get_mut().expect("expected KernelMapper not to be locked re-entrant while initializing LAPIC");
let mapper = mapper
.get_mut()
.expect("expected KernelMapper not to be locked re-entrant while initializing LAPIC");
let physaddr = PhysicalAddress::new(rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000);
let virtaddr = RmmA::phys_to_virt(physaddr);
self.address = virtaddr.data();
self.x2 = cpuid().map_or(false, |cpuid| {
cpuid.get_feature_info().map_or(false, |feature_info| {
feature_info.has_x2apic()
})
cpuid
.get_feature_info()
.map_or(false, |feature_info| feature_info.has_x2apic())
});
if ! self.x2 {
if !self.x2 {
log::info!("Detected xAPIC at {:#x}", physaddr.data());
if let Some((_entry, _, flush)) = mapper.unmap_phys(virtaddr, true) {
// Unmap xAPIC page if already mapped
@@ -112,15 +116,15 @@ impl LocalApic {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_ICR) }
} else {
unsafe {
(self.read(0x310) as u64) << 32 | self.read(0x300) as u64
}
unsafe { (self.read(0x310) as u64) << 32 | self.read(0x300) as u64 }
}
}
pub fn set_icr(&mut self, value: u64) {
if self.x2 {
unsafe { wrmsr(IA32_X2APIC_ICR, value); }
unsafe {
wrmsr(IA32_X2APIC_ICR, value);
}
} else {
unsafe {
const PENDING: u32 = 1 << 12;
+3 -3
View File
@@ -1,12 +1,12 @@
pub mod cpu;
#[cfg(feature = "acpi")]
pub mod hpet;
pub mod ioapic;
pub mod local_apic;
pub mod pic;
pub mod pit;
pub mod rtc;
pub mod serial;
#[cfg(feature = "acpi")]
pub mod hpet;
#[cfg(feature = "system76_ec_debug")]
pub mod system76_ec;
@@ -16,7 +16,7 @@ pub unsafe fn init() {
pic::init();
local_apic::init(&mut KernelMapper::lock());
}
pub unsafe fn init_after_acpi() {
pub unsafe fn init_after_acpi() {
// this will disable the IOAPIC if needed.
//ioapic::init(mapper);
}
+4 -2
View File
@@ -1,5 +1,7 @@
use crate::syscall::io::{Io, Pio};
use crate::arch::interrupt::irq;
use crate::{
arch::interrupt::irq,
syscall::io::{Io, Pio},
};
pub static mut MASTER: Pic = Pic::new(0x20);
pub static mut SLAVE: Pic = Pic::new(0xA0);
+4 -2
View File
@@ -1,5 +1,7 @@
use crate::syscall::io::{Io, Pio};
use crate::time;
use crate::{
syscall::io::{Io, Pio},
time,
};
pub fn init() {
let mut rtc = Rtc::new();
+13 -9
View File
@@ -1,7 +1,6 @@
use crate::devices::uart_16550::SerialPort;
#[cfg(feature = "lpss_debug")]
use crate::syscall::io::Mmio;
use crate::syscall::io::Pio;
use crate::{devices::uart_16550::SerialPort, syscall::io::Pio};
use spin::Mutex;
pub static COM1: Mutex<SerialPort<Pio<u8>>> = Mutex::new(SerialPort::<Pio<u8>>::new(0x3F8));
@@ -22,19 +21,24 @@ pub unsafe fn init() {
let address = crate::PHYS_OFFSET + 0xFE032000;
{
use crate::paging::{ActivePageTable, Page, VirtualAddress, entry::EntryFlags};
use crate::memory::{Frame, PhysicalAddress};
use crate::{
memory::{Frame, PhysicalAddress},
paging::{entry::EntryFlags, ActivePageTable, Page, VirtualAddress},
};
let mut active_table = ActivePageTable::new();
let page = Page::containing_address(VirtualAddress::new(address));
let frame = Frame::containing_address(PhysicalAddress::new(address - crate::PHYS_OFFSET));
let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE);
let frame =
Frame::containing_address(PhysicalAddress::new(address - crate::PHYS_OFFSET));
let result = active_table.map_to(
page,
frame,
EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE,
);
result.flush(&mut active_table);
}
let lpss = SerialPort::<Mmio<u32>>::new(
crate::PHYS_OFFSET + 0xFE032000
);
let lpss = SerialPort::<Mmio<u32>>::new(crate::PHYS_OFFSET + 0xFE032000);
lpss.init();
*LPSS.lock() = Some(lpss);
+1 -3
View File
@@ -13,9 +13,7 @@ pub struct System76Ec {
impl System76Ec {
pub fn new() -> Option<Self> {
let mut system76_ec = Self {
base: 0x0E00,
};
let mut system76_ec = Self { base: 0x0E00 };
if system76_ec.probe() {
Some(system76_ec)
} else {
+65 -27
View File
@@ -1,17 +1,19 @@
//! Global descriptor table
use core::convert::TryInto;
use core::mem;
use core::{convert::TryInto, mem};
use crate::LogicalCpuId;
use crate::paging::{RmmA, RmmArch};
use crate::percpu::PercpuBlock;
use crate::{
paging::{RmmA, RmmArch},
percpu::PercpuBlock,
LogicalCpuId,
};
use x86::bits64::task::TaskStateSegment;
use x86::Ring;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector};
use x86::task;
use x86::{
bits64::task::TaskStateSegment,
dtables::{self, DescriptorTablePointer},
segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector},
task, Ring,
};
pub const GDT_NULL: usize = 0;
pub const GDT_KERNEL_CODE: usize = 1;
@@ -44,9 +46,19 @@ static mut INIT_GDT: [GdtEntry; 3] = [
// Null
GdtEntry::new(0, 0, 0, 0),
// Kernel code
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// Kernel data
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
];
// Later copied into the actual GDT with various fields set.
@@ -54,15 +66,40 @@ const BASE_GDT: [GdtEntry; 8] = [
// Null
GdtEntry::new(0, 0, 0, 0),
// Kernel code
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// Kernel data
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// Dummy 32-bit user code - apparently necessary for SYSRET. We restrict it to ring 0 anyway.
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_PROTECTED_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_PROTECTED_MODE,
),
// User data
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// User (64-bit) code
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
0,
0,
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// TSS
GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0),
// TSS must be 16 bytes long, twice the normal size
@@ -104,8 +141,9 @@ pub unsafe fn pcr() -> *mut ProcessorControlRegion {
#[cfg(feature = "pti")]
pub unsafe fn set_tss_stack(stack: usize) {
use super::pti::{PTI_CPU_STACK, PTI_CONTEXT_STACK};
core::ptr::addr_of_mut!((*pcr()).tss.rsp[0]).write((PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()) as u64);
use super::pti::{PTI_CONTEXT_STACK, PTI_CPU_STACK};
core::ptr::addr_of_mut!((*pcr()).tss.rsp[0])
.write((PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()) as u64);
PTI_CONTEXT_STACK = stack;
}
@@ -145,7 +183,8 @@ unsafe fn load_segments() {
#[cold]
pub unsafe fn init_paging(stack_offset: usize, cpu_id: LogicalCpuId) {
let pcr_frame = crate::memory::allocate_frames(1).expect("failed to allocate PCR");
let pcr = &mut *(RmmA::phys_to_virt(pcr_frame.start_address()).data() as *mut ProcessorControlRegion);
let pcr =
&mut *(RmmA::phys_to_virt(pcr_frame.start_address()).data() as *mut ProcessorControlRegion);
pcr.self_ref = pcr as *mut ProcessorControlRegion as usize;
@@ -157,10 +196,7 @@ pub unsafe fn init_paging(stack_offset: usize, cpu_id: LogicalCpuId) {
.expect("main GDT way too large");
let base = pcr.gdt.as_ptr() as *const SegmentDescriptor;
let gdtr: DescriptorTablePointer<SegmentDescriptor> = DescriptorTablePointer {
limit,
base,
};
let gdtr: DescriptorTablePointer<SegmentDescriptor> = DescriptorTablePointer { limit, base };
{
pcr.tss.iomap_base = 0xFFFF;
@@ -172,7 +208,9 @@ pub unsafe fn init_paging(stack_offset: usize, cpu_id: LogicalCpuId) {
pcr.gdt[GDT_TSS].set_offset(tss_lo);
pcr.gdt[GDT_TSS].set_limit(mem::size_of::<TaskStateSegment>() as u32);
(&mut pcr.gdt[GDT_TSS_HIGH] as *mut GdtEntry).cast::<u32>().write(tss_hi);
(&mut pcr.gdt[GDT_TSS_HIGH] as *mut GdtEntry)
.cast::<u32>()
.write(tss_hi);
}
// Load the new GDT, which is correctly located in thread local storage.
@@ -214,7 +252,7 @@ pub struct GdtEntry {
pub offsetm: u8,
pub access: u8,
pub flags_limith: u8,
pub offseth: u8
pub offseth: u8,
}
impl GdtEntry {
@@ -225,7 +263,7 @@ impl GdtEntry {
offsetm: (offset >> 16) as u8,
access,
flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F,
offseth: (offset >> 24) as u8
offseth: (offset >> 24) as u8,
}
}
+66 -21
View File
@@ -1,22 +1,31 @@
use core::num::NonZeroU8;
use core::sync::atomic::{AtomicU64, Ordering};
use core::mem;
use core::{
mem,
num::NonZeroU8,
sync::atomic::{AtomicU64, Ordering},
};
use alloc::boxed::Box;
use hashbrown::HashMap;
use x86::segmentation::Descriptor as X86IdtEntry;
use x86::dtables::{self, DescriptorTablePointer};
use x86::{
dtables::{self, DescriptorTablePointer},
segmentation::Descriptor as X86IdtEntry,
};
use crate::{interrupt::*, LogicalCpuId};
use crate::interrupt::irq::{__generic_interrupts_end, __generic_interrupts_start};
use crate::ipi::IpiKind;
use crate::{
interrupt::{
irq::{__generic_interrupts_end, __generic_interrupts_start},
*,
},
ipi::IpiKind,
LogicalCpuId,
};
use spin::RwLock;
pub static mut INIT_IDTR: DescriptorTablePointer<X86IdtEntry> = DescriptorTablePointer {
limit: 0,
base: 0 as *const X86IdtEntry
base: 0 as *const X86IdtEntry,
};
pub type IdtEntries = [IdtEntry; 256];
@@ -47,7 +56,8 @@ impl Idt {
let byte_index = index / 64;
let bit = index % 64;
{ &self.reservations[usize::from(byte_index)] }.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel);
{ &self.reservations[usize::from(byte_index)] }
.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel);
}
#[inline]
pub fn is_reserved_mut(&mut self, index: u8) -> bool {
@@ -62,7 +72,8 @@ impl Idt {
let byte_index = index / 64;
let bit = index % 64;
*{ &mut self.reservations[usize::from(byte_index)] }.get_mut() |= u64::from(reserved) << bit;
*{ &mut self.reservations[usize::from(byte_index)] }.get_mut() |=
u64::from(reserved) << bit;
}
}
@@ -76,7 +87,18 @@ pub fn is_reserved(cpu_id: LogicalCpuId, index: u8) -> bool {
let byte_index = index / 64;
let bit = index % 64;
{ &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.load(Ordering::Acquire) & (1 << bit) != 0
{
&IDTS
.read()
.as_ref()
.unwrap()
.get(&cpu_id)
.unwrap()
.reservations[usize::from(byte_index)]
}
.load(Ordering::Acquire)
& (1 << bit)
!= 0
}
#[inline]
@@ -84,13 +106,22 @@ pub fn set_reserved(cpu_id: LogicalCpuId, index: u8, reserved: bool) {
let byte_index = index / 64;
let bit = index % 64;
{ &IDTS.read().as_ref().unwrap().get(&cpu_id).unwrap().reservations[usize::from(byte_index)] }.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel);
{
&IDTS
.read()
.as_ref()
.unwrap()
.get(&cpu_id)
.unwrap()
.reservations[usize::from(byte_index)]
}
.fetch_or(u64::from(reserved) << bit, Ordering::AcqRel);
}
pub fn allocate_interrupt() -> Option<NonZeroU8> {
let cpu_id = crate::cpu_id();
for number in 50..=254 {
if ! is_reserved(cpu_id, number) {
if !is_reserved(cpu_id, number) {
set_reserved(cpu_id, number, true);
return Some(unsafe { NonZeroU8::new_unchecked(number) });
}
@@ -107,7 +138,12 @@ pub unsafe fn init() {
}
const fn new_idt_reservations() -> [AtomicU64; 4] {
[AtomicU64::new(0), AtomicU64::new(0), AtomicU64::new(0), AtomicU64::new(0)]
[
AtomicU64::new(0),
AtomicU64::new(0),
AtomicU64::new(0),
AtomicU64::new(0),
]
}
/// Initialize the IDT for a
@@ -118,7 +154,9 @@ pub unsafe fn init_paging_post_heap(cpu_id: LogicalCpuId) {
if cpu_id == LogicalCpuId::BSP {
idts_btree.insert(cpu_id, &mut INIT_BSP_IDT);
} else {
let idt = idts_btree.entry(cpu_id).or_insert_with(|| Box::leak(Box::new(Idt::new())));
let idt = idts_btree
.entry(cpu_id)
.or_insert_with(|| Box::leak(Box::new(Idt::new())));
init_generic(cpu_id, idt);
}
}
@@ -199,7 +237,10 @@ pub unsafe fn init_generic(cpu_id: LogicalCpuId, idt: &mut Idt) {
current_idt[30].set_func(exception::security);
// 31 reserved
assert_eq!(__generic_interrupts_end as usize - __generic_interrupts_start as usize, 224 * 8);
assert_eq!(
__generic_interrupts_end as usize - __generic_interrupts_start as usize,
224 * 8
);
for i in 0..224 {
current_idt[i + 32].set_func(mem::transmute(__generic_interrupts_start as usize + i * 8));
@@ -282,7 +323,7 @@ pub struct IdtEntry {
attribute: u8,
offsetm: u16,
offseth: u32,
_zero2: u32
_zero2: u32,
}
impl IdtEntry {
@@ -294,7 +335,7 @@ impl IdtEntry {
attribute: 0,
offsetm: 0,
offseth: 0,
_zero2: 0
_zero2: 0,
}
}
@@ -303,7 +344,11 @@ impl IdtEntry {
}
pub fn set_ist(&mut self, ist: u8) {
assert_eq!(ist & 0x07, ist, "interrupt stack table must be within 0..=7");
assert_eq!(
ist & 0x07,
ist,
"interrupt stack table must be within 0..=7"
);
self.zero &= 0xF8;
self.zero |= ist;
}
@@ -316,7 +361,7 @@ impl IdtEntry {
}
// A function to set the offset more easily
pub fn set_func(&mut self, func: unsafe extern fn()) {
pub fn set_func(&mut self, func: unsafe extern "C" fn()) {
self.set_flags(IdtFlags::PRESENT | IdtFlags::RING_0 | IdtFlags::INTERRUPT);
self.set_offset((crate::gdt::GDT_KERNEL_CODE as u16) << 3, func as usize);
}
+23 -14
View File
@@ -1,17 +1,11 @@
use x86::irq::PageFaultError;
use crate::memory::GenericPfFlags;
use crate::ptrace;
use crate::{
interrupt::stack_trace,
paging::VirtualAddress,
syscall::flag::*,
interrupt_stack,
interrupt_error,
interrupt::stack_trace, interrupt_error, interrupt_stack, memory::GenericPfFlags,
paging::VirtualAddress, ptrace, syscall::flag::*,
};
extern {
extern "C" {
fn ksignal(signal: usize);
}
@@ -145,11 +139,26 @@ interrupt_error!(page, |stack, code| {
let arch_flags = PageFaultError::from_bits_truncate(code as u32);
let mut generic_flags = GenericPfFlags::empty();
generic_flags.set(GenericPfFlags::PRESENT, arch_flags.contains(PageFaultError::P));
generic_flags.set(GenericPfFlags::INVOLVED_WRITE, arch_flags.contains(PageFaultError::WR));
generic_flags.set(GenericPfFlags::USER_NOT_SUPERVISOR, arch_flags.contains(PageFaultError::US));
generic_flags.set(GenericPfFlags::INVL, arch_flags.contains(PageFaultError::RSVD));
generic_flags.set(GenericPfFlags::INSTR_NOT_DATA, arch_flags.contains(PageFaultError::ID));
generic_flags.set(
GenericPfFlags::PRESENT,
arch_flags.contains(PageFaultError::P),
);
generic_flags.set(
GenericPfFlags::INVOLVED_WRITE,
arch_flags.contains(PageFaultError::WR),
);
generic_flags.set(
GenericPfFlags::USER_NOT_SUPERVISOR,
arch_flags.contains(PageFaultError::US),
);
generic_flags.set(
GenericPfFlags::INVL,
arch_flags.contains(PageFaultError::RSVD),
);
generic_flags.set(
GenericPfFlags::INSTR_NOT_DATA,
arch_flags.contains(PageFaultError::ID),
);
if crate::memory::page_fault_handler(stack, generic_flags, cr2).is_err() {
println!("Page fault: {:>016X} {:#?}", cr2.data(), arch_flags);
+37 -20
View File
@@ -1,7 +1,6 @@
use core::mem;
use crate::memory::ArchIntCtx;
use crate::syscall::IntRegisters;
use crate::{memory::ArchIntCtx, syscall::IntRegisters};
use super::super::flags::*;
@@ -65,7 +64,6 @@ pub struct IretRegisters {
// In x86 Protected Mode, i.e. 32-bit kernels, the following two registers are conditionally
// pushed if the privilege ring changes. In x86 Long Mode however, i.e. 64-bit kernels, they
// are unconditionally pushed, mostly due to stack alignment requirements.
pub rsp: usize,
pub ss: usize,
}
@@ -83,7 +81,10 @@ impl IretRegisters {
let fsbase = x86::msr::rdmsr(x86::msr::IA32_FS_BASE);
let gsbase = x86::msr::rdmsr(x86::msr::IA32_KERNEL_GSBASE);
let kgsbase = x86::msr::rdmsr(x86::msr::IA32_GS_BASE);
println!("FSBASE {:016x}\nGSBASE {:016x}\nKGSBASE {:016x}", fsbase, gsbase, kgsbase);
println!(
"FSBASE {:016x}\nGSBASE {:016x}\nKGSBASE {:016x}",
fsbase, gsbase, kgsbase
);
}
}
}
@@ -190,7 +191,8 @@ impl InterruptStack {
#[macro_export]
macro_rules! push_scratch {
() => { "
() => {
"
// Push scratch registers
push rcx
push rdx
@@ -200,11 +202,13 @@ macro_rules! push_scratch {
push r9
push r10
push r11
" };
"
};
}
#[macro_export]
macro_rules! pop_scratch {
() => { "
() => {
"
// Pop scratch registers
pop r11
pop r10
@@ -215,12 +219,14 @@ macro_rules! pop_scratch {
pop rdx
pop rcx
pop rax
" };
"
};
}
#[macro_export]
macro_rules! push_preserved {
() => { "
() => {
"
// Push preserved registers
push rbx
push rbp
@@ -228,11 +234,13 @@ macro_rules! push_preserved {
push r13
push r14
push r15
" };
"
};
}
#[macro_export]
macro_rules! pop_preserved {
() => { "
() => {
"
// Pop preserved registers
pop r15
pop r14
@@ -240,27 +248,32 @@ macro_rules! pop_preserved {
pop r12
pop rbp
pop rbx
" };
"
};
}
macro_rules! swapgs_iff_ring3_fast {
// TODO: Spectre V1: LFENCE?
() => { "
() => {
"
// Check whether the last two bits RSP+8 (code segment) are equal to zero.
test QWORD PTR [rsp + 8], 0x3
// Skip the SWAPGS instruction if CS & 0b11 == 0b00.
jz 1f
swapgs
1:
" };
"
};
}
macro_rules! swapgs_iff_ring3_fast_errorcode {
// TODO: Spectre V1: LFENCE?
() => { "
() => {
"
test QWORD PTR [rsp + 16], 0x3
jz 1f
swapgs
1:
" };
"
};
}
macro_rules! conditional_swapgs_paranoid {
@@ -328,17 +341,21 @@ macro_rules! conditional_swapgs_paranoid {
) }
}
macro_rules! conditional_swapgs_back_paranoid {
() => { "
() => {
"
test bl, bl
jnz 1f
swapgs
1:
" }
"
};
}
macro_rules! nop {
() => { "
() => {
"
// Unused: {IA32_GS_BASE} {PCR_GDT_OFFSET}
" }
"
};
}
#[macro_export]
+1 -2
View File
@@ -1,7 +1,6 @@
use x86::tlb;
use crate::context;
use crate::device::local_apic::LOCAL_APIC;
use crate::{context, device::local_apic::LOCAL_APIC};
interrupt!(wakeup, || {
LOCAL_APIC.eoi();
+43 -17
View File
@@ -2,14 +2,21 @@ use core::sync::atomic::{AtomicUsize, Ordering};
use alloc::vec::Vec;
use crate::{interrupt, interrupt_stack};
use crate::context::timeout;
use crate::device::{local_apic, ioapic, pic, pit};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::{debug_input, debug_notify};
use crate::scheme::serio::serio_input;
use crate::{context, time};
use crate::{
context,
context::timeout,
device::{
ioapic, local_apic, pic, pit,
serial::{COM1, COM2},
},
interrupt, interrupt_stack,
ipi::{ipi, IpiKind, IpiTarget},
scheme::{
debug::{debug_input, debug_notify},
serio::serio_input,
},
time,
};
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -33,9 +40,13 @@ pub fn spurious_count() -> usize {
pub fn spurious_irq_resource() -> syscall::Result<Vec<u8>> {
match irq_method() {
IrqMethod::Apic => Ok(Vec::from(&b"(not implemented for APIC yet)"[..])),
IrqMethod::Pic => {
Ok(format!("{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n", spurious_count_irq7(), spurious_count_irq15(), spurious_count()).into_bytes())
}
IrqMethod::Pic => Ok(format!(
"{}\tIRQ7\n{}\tIRQ15\n{}\ttotal\n",
spurious_count_irq7(),
spurious_count_irq15(),
spurious_count()
)
.into_bytes()),
}
}
@@ -55,7 +66,7 @@ fn irq_method() -> IrqMethod {
}
}
extern {
extern "C" {
// triggers irq scheme
fn irq_trigger(irq: u8);
}
@@ -64,7 +75,11 @@ extern {
/// scheme user unmasks it ("acknowledges" it).
unsafe fn trigger(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_mask(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_mask(irq)
}
}
IrqMethod::Apic => ioapic_mask(irq),
}
irq_trigger(irq);
@@ -74,7 +89,11 @@ unsafe fn trigger(irq: u8) {
/// processed the IRQ.
pub unsafe fn acknowledge(irq: usize) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_unmask(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_unmask(irq)
}
}
IrqMethod::Apic => ioapic_unmask(irq),
}
}
@@ -82,7 +101,11 @@ pub unsafe fn acknowledge(irq: usize) {
/// Sends an end-of-interrupt, so that the interrupt controller can go on to the next one.
pub unsafe fn eoi(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_eoi(irq) },
IrqMethod::Pic => {
if irq < 16 {
pic_eoi(irq)
}
}
IrqMethod::Apic => lapic_eoi(),
}
}
@@ -242,7 +265,7 @@ interrupt!(ata2, || {
if irq_method() == IrqMethod::Pic && pic::SLAVE.isr() & (1 << 7) == 0 {
SPURIOUS_COUNT_IRQ15.fetch_add(1, Ordering::Relaxed);
pic::MASTER.ack();
return
return;
}
trigger(15);
eoi(15);
@@ -259,7 +282,10 @@ interrupt!(aux_timer, || {
});
interrupt!(lapic_error, || {
println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr());
println!(
"Local apic internal error: ESR={:#0x}",
local_apic::LOCAL_APIC.esr()
);
lapic_eoi();
});
+8 -5
View File
@@ -9,11 +9,12 @@ pub mod irq;
pub mod syscall;
pub mod trace;
pub use self::handler::InterruptStack;
pub use self::trace::stack_trace;
pub use self::{handler::InterruptStack, trace::stack_trace};
pub use super::idt::{available_irqs_iter, is_reserved, set_reserved};
pub use super::device::local_apic::bsp_apic_id;
pub use super::{
device::local_apic::bsp_apic_id,
idt::{available_irqs_iter, is_reserved, set_reserved},
};
/// Clear interrupts
#[inline(always)]
@@ -53,5 +54,7 @@ pub unsafe fn halt() {
/// Safe because it is similar to a NOP, and has no memory effects
#[inline(always)]
pub fn pause() {
unsafe { core::arch::asm!("pause", options(nomem, nostack)); }
unsafe {
core::arch::asm!("pause", options(nomem, nostack));
}
}
+36 -10
View File
@@ -1,12 +1,14 @@
use crate::{
arch::{gdt, interrupt::InterruptStack},
context,
ptrace,
syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL},
context, ptrace, syscall,
syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_POST_SYSCALL, PTRACE_STOP_PRE_SYSCALL},
};
use core::mem::offset_of;
use x86::{bits64::{rflags::RFlags, task::TaskStateSegment}, msr, segmentation::SegmentSelector};
use x86::{
bits64::{rflags::RFlags, task::TaskStateSegment},
msr,
segmentation::SegmentSelector,
};
pub unsafe fn init() {
// IA32_STAR[31:0] are reserved.
@@ -46,7 +48,12 @@ pub unsafe fn init() {
// user and kernel mode), VM8086 (not used at all), and VIF/VIP (system-level status flags?).
let mask_critical = RFlags::FLAGS_DF | RFlags::FLAGS_IF | RFlags::FLAGS_TF | RFlags::FLAGS_AC;
let mask_other = RFlags::FLAGS_CF | RFlags::FLAGS_PF | RFlags::FLAGS_AF | RFlags::FLAGS_ZF | RFlags::FLAGS_SF | RFlags::FLAGS_OF;
let mask_other = RFlags::FLAGS_CF
| RFlags::FLAGS_PF
| RFlags::FLAGS_AF
| RFlags::FLAGS_ZF
| RFlags::FLAGS_SF
| RFlags::FLAGS_OF;
msr::wrmsr(msr::IA32_FMASK, (mask_critical | mask_other).bits());
let efer = msr::rdmsr(msr::IA32_EFER);
@@ -68,7 +75,7 @@ macro_rules! with_interrupt_stack {
}
ptrace::breakpoint_callback(PTRACE_STOP_POST_SYSCALL, None);
}}
}};
}
#[no_mangle]
@@ -76,7 +83,15 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
let _guard = ptrace::set_process_regs(stack);
with_interrupt_stack!(|stack| {
let scratch = &stack.scratch;
syscall::syscall(scratch.rax, scratch.rdi, scratch.rsi, scratch.rdx, scratch.r10, scratch.r8, stack)
syscall::syscall(
scratch.rax,
scratch.rdi,
scratch.rsi,
scratch.rdx,
scratch.r10,
scratch.r8,
stack,
)
});
}
@@ -193,13 +208,24 @@ interrupt_stack!(syscall, |stack| {
let context = contexts.current();
if let Some(current) = context {
let current = current.read();
println!("Warning: Context {} used deprecated `int 0x80` construct", current.name);
println!(
"Warning: Context {} used deprecated `int 0x80` construct",
current.name
);
} else {
println!("Warning: Unknown context used deprecated `int 0x80` construct");
}
}
let scratch = &stack.scratch;
syscall::syscall(scratch.rax, stack.preserved.rbx, scratch.rcx, scratch.rdx, scratch.rsi, scratch.rdi, stack)
syscall::syscall(
scratch.rax,
stack.preserved.rbx,
scratch.rcx,
scratch.rdx,
scratch.rsi,
scratch.rdi,
stack,
)
})
});
+22 -10
View File
@@ -3,7 +3,10 @@ use core::{mem, str};
use goblin::elf::sym;
use rustc_demangle::demangle;
use crate::{paging::{KernelMapper, VirtualAddress}, USER_END_OFFSET};
use crate::{
paging::{KernelMapper, VirtualAddress},
USER_END_OFFSET,
};
/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing
@@ -21,7 +24,11 @@ pub unsafe fn stack_trace() {
if let Some(rip_rbp) = rbp.checked_add(mem::size_of::<usize>()) {
let rbp_virt = VirtualAddress::new(rbp);
let rip_rbp_virt = VirtualAddress::new(rip_rbp);
if rbp_virt.data() >= USER_END_OFFSET && rip_rbp_virt.data() >= USER_END_OFFSET && mapper.translate(rbp_virt).is_some() && mapper.translate(rip_rbp_virt).is_some() {
if rbp_virt.data() >= USER_END_OFFSET
&& rip_rbp_virt.data() >= USER_END_OFFSET
&& mapper.translate(rbp_virt).is_some()
&& mapper.translate(rip_rbp_virt).is_some()
{
let rip = (rip_rbp as *const usize).read();
if rip == 0 {
println!(" {:>016X}: EMPTY RETURN", rbp);
@@ -45,11 +52,12 @@ pub unsafe fn stack_trace() {
//TODO: Do not create Elf object for every symbol lookup
#[inline(never)]
pub unsafe fn symbol_trace(addr: usize) {
use core::slice;
use core::sync::atomic::Ordering;
use core::{slice, sync::atomic::Ordering};
use crate::elf::Elf;
use crate::start::{KERNEL_BASE, KERNEL_SIZE};
use crate::{
elf::Elf,
start::{KERNEL_BASE, KERNEL_SIZE},
};
let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::PHYS_OFFSET) as *const u8;
let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));
@@ -65,10 +73,14 @@ pub unsafe fn symbol_trace(addr: usize) {
if let Some(symbols) = elf.symbols() {
for sym in symbols {
if sym::st_type(sym.st_info) == sym::STT_FUNC
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
{
println!(" {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize);
println!(
" {:>016X}+{:>04X}",
sym.st_value,
addr - sym.st_value as usize
);
if let Some(strtab) = strtab_opt {
let start = strtab.sh_offset as usize + sym.st_name as usize;
@@ -82,7 +94,7 @@ pub unsafe fn symbol_trace(addr: usize) {
}
if end > start {
let sym_slice = &elf.data[start .. end - 1];
let sym_slice = &elf.data[start..end - 1];
if let Ok(sym_name) = str::from_utf8(sym_slice) {
println!(" {:#}", demangle(sym_name));
}
-1
View File
@@ -95,4 +95,3 @@ macro_rules! alternative_auto(
",
) }
);
+4 -2
View File
@@ -1,7 +1,9 @@
use x86::controlregs::Cr4;
use crate::LogicalCpuId;
use crate::cpuid::{cpuid_always, has_ext_feat};
use crate::{
cpuid::{cpuid_always, has_ext_feat},
LogicalCpuId,
};
pub unsafe fn init(cpu_id: LogicalCpuId) {
if has_ext_feat(|feat| feat.has_umip()) {
+12 -6
View File
@@ -68,9 +68,10 @@ pub mod flags {
pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -> u8 {
// TODO: spectre_v1
core::arch::asm!(alternative!(
feature: "smap",
then: ["
core::arch::asm!(
alternative!(
feature: "smap",
then: ["
xor eax, eax
mov rcx, rdx
stac
@@ -78,19 +79,24 @@ pub unsafe extern "C" fn arch_copy_to_user(dst: usize, src: usize, len: usize) -
clac
ret
"],
default: ["
default: ["
xor eax, eax
mov rcx, rdx
rep movsb
ret
"]
), options(noreturn));
),
options(noreturn)
);
}
pub use arch_copy_to_user as arch_copy_from_user;
// TODO: This doesn't need to be arch-specific, right?
pub unsafe fn bootstrap_mem(bootstrap: &Bootstrap) -> &'static [u8] {
core::slice::from_raw_parts(CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8, bootstrap.page_count * PAGE_SIZE)
core::slice::from_raw_parts(
CurrentRmmArch::phys_to_virt(bootstrap.base.start_address()).data() as *const u8,
bootstrap.page_count * PAGE_SIZE,
)
}
pub use alternative::kfx_size;
+9 -3
View File
@@ -4,16 +4,22 @@ use super::RmmA;
pub use rmm::{Flusher, PageFlush, PageFlushAll};
pub struct InactiveFlusher { _inner: () }
pub struct InactiveFlusher {
_inner: (),
}
impl InactiveFlusher {
// TODO: cpu id
pub fn new() -> Self { Self { _inner: () } }
pub fn new() -> Self {
Self { _inner: () }
}
}
impl Flusher<RmmA> for InactiveFlusher {
fn consume(&mut self, flush: PageFlush<RmmA>) {
// TODO: Push to TLB "mailbox" or tell it to reload CR3 if there are too many entries.
unsafe { flush.ignore(); }
unsafe {
flush.ignore();
}
}
}
impl Drop for InactiveFlusher {
+10 -10
View File
@@ -5,15 +5,8 @@ use core::fmt::Debug;
use x86::msr;
pub use rmm::{
Arch as RmmArch,
Flusher,
PageFlags,
PhysicalAddress,
TableKind,
VirtualAddress,
};
pub use super::CurrentRmmArch as RmmA;
pub use rmm::{Arch as RmmArch, Flusher, PageFlags, PhysicalAddress, TableKind, VirtualAddress};
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
pub use crate::rmm::KernelMapper;
@@ -92,7 +85,10 @@ impl Page {
}
pub fn range_inclusive(start: Page, r#final: Page) -> PageIter {
PageIter { start, end: r#final.next() }
PageIter {
start,
end: r#final.next(),
}
}
pub fn range_exclusive(start: Page, end: Page) -> PageIter {
PageIter { start, end }
@@ -112,7 +108,11 @@ impl Page {
}
impl Debug for Page {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "[page at {:p}]", self.start_address().data() as *const u8)
write!(
f,
"[page at {:p}]",
self.start_address().data() as *const u8
)
}
}
+11 -9
View File
@@ -4,9 +4,9 @@ use core::ptr;
#[cfg(feature = "pti")]
use crate::memory::Frame;
#[cfg(feature = "pti")]
use crate::paging::ActivePageTable;
#[cfg(feature = "pti")]
use crate::paging::entry::EntryFlags;
#[cfg(feature = "pti")]
use crate::paging::ActivePageTable;
#[cfg(feature = "pti")]
#[thread_local]
@@ -26,11 +26,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
let new_rsp = new - offset_rsp;
ptr::copy_nonoverlapping(
old_rsp as *const u8,
new_rsp as *mut u8,
offset_rsp
);
ptr::copy_nonoverlapping(old_rsp as *const u8, new_rsp as *mut u8, offset_rsp);
asm!("", out("rsp") new_rsp);
}
@@ -53,14 +49,20 @@ 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,
);
}
#[cfg(feature = "pti")]
#[inline(always)]
pub unsafe extern "C" 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() };
+139 -90
View File
@@ -1,24 +1,11 @@
use core::{
cmp,
mem,
slice,
sync::atomic::{self, AtomicUsize, Ordering}, cell::SyncUnsafeCell,
cell::SyncUnsafeCell,
cmp, mem, slice,
sync::atomic::{self, AtomicUsize, Ordering},
};
use rmm::{
KILOBYTE,
MEGABYTE,
Arch,
BuddyAllocator,
BumpAllocator,
FrameAllocator,
FrameCount,
FrameUsage,
MemoryArea,
PageFlags,
PageMapper,
PhysicalAddress,
TableKind,
VirtualAddress,
Arch, BuddyAllocator, BumpAllocator, FrameAllocator, FrameCount, FrameUsage, MemoryArea,
PageFlags, PageMapper, PhysicalAddress, TableKind, VirtualAddress, KILOBYTE, MEGABYTE,
};
use spin::Mutex;
@@ -63,11 +50,16 @@ unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> PageFlags<A> {
unsafe fn inner<A: Arch>(
areas: &'static [MemoryArea],
kernel_base: usize, kernel_size_aligned: usize,
stack_base: usize, stack_size_aligned: usize,
env_base: usize, env_size_aligned: usize,
acpi_base: usize, acpi_size_aligned: usize,
initfs_base: usize, initfs_size_aligned: usize,
kernel_base: usize,
kernel_size_aligned: usize,
stack_base: usize,
stack_size_aligned: usize,
env_base: usize,
env_size_aligned: usize,
acpi_base: usize,
acpi_size_aligned: usize,
initfs_base: usize,
initfs_size_aligned: usize,
) -> BuddyAllocator<A> {
// First, calculate how much memory we have
let mut size = 0;
@@ -84,10 +76,8 @@ unsafe fn inner<A: Arch>(
let mut bump_allocator = BumpAllocator::<A>::new(areas, 0);
{
let mut mapper = PageMapper::<A, _>::create(
TableKind::Kernel,
&mut bump_allocator
).expect("failed to create Mapper");
let mut mapper = PageMapper::<A, _>::create(TableKind::Kernel, &mut bump_allocator)
.expect("failed to create Mapper");
// Map all physical areas at PHYS_OFFSET
for area in areas.iter() {
@@ -95,11 +85,9 @@ unsafe fn inner<A: Arch>(
let phys = area.base.add(i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -109,19 +97,15 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(kernel_base + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(crate::KERNEL_OFFSET + i * A::PAGE_SIZE);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
let virt = A::phys_to_virt(phys);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
@@ -131,11 +115,9 @@ unsafe fn inner<A: Arch>(
let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
};
@@ -148,8 +130,8 @@ unsafe fn inner<A: Arch>(
// Ensure graphical debug region remains paged
#[cfg(feature = "graphical_debug")]
{
use crate::devices::graphical_debug::FRAMEBUFFER;
use super::paging::entry::EntryFlags;
use crate::devices::graphical_debug::FRAMEBUFFER;
let (phys, virt, size) = *FRAMEBUFFER.lock();
@@ -157,14 +139,13 @@ unsafe fn inner<A: Arch>(
for i in 0..pages {
let phys = PhysicalAddress::new(phys + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(virt + i * A::PAGE_SIZE);
let flags = PageFlags::new().write(true)
let flags = PageFlags::new()
.write(true)
// Write combining flag
.custom_flag(EntryFlags::HUGE_PAGE.bits(), true);
let flush = mapper.map_phys(
virt,
phys,
flags
).expect("failed to map frame");
let flush = mapper
.map_phys(virt, phys, flags)
.expect("failed to map frame");
flush.ignore(); // Not the active table
}
}
@@ -184,7 +165,10 @@ unsafe fn inner<A: Arch>(
// Create the physical memory map
let offset = bump_allocator.offset();
log::info!("Permanently used: {} KB", (offset + (KILOBYTE - 1)) / KILOBYTE);
log::info!(
"Permanently used: {} KB",
(offset + (KILOBYTE - 1)) / KILOBYTE
);
BuddyAllocator::<A>::new(bump_allocator).expect("failed to create BuddyAllocator")
}
@@ -228,10 +212,12 @@ impl core::fmt::Debug for LockedAllocator {
}
}
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new([MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512]);
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new(
[MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512],
);
static AREA_COUNT: SyncUnsafeCell<u16> = SyncUnsafeCell::new(0);
pub fn areas() -> &'static [MemoryArea] {
@@ -263,7 +249,12 @@ pub struct KernelMapper {
impl KernelMapper {
fn lock_inner(current_processor: usize) -> bool {
loop {
match LOCK_OWNER.compare_exchange_weak(NO_PROCESSOR, current_processor, Ordering::Acquire, Ordering::Relaxed) {
match LOCK_OWNER.compare_exchange_weak(
NO_PROCESSOR,
current_processor,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => break,
// already owned by this hardware thread
Err(id) if id == current_processor => break,
@@ -277,15 +268,20 @@ impl KernelMapper {
prev_count > 0
}
pub unsafe fn lock_for_manual_mapper(current_processor: LogicalCpuId, mapper: crate::paging::PageMapper) -> Self {
pub unsafe fn lock_for_manual_mapper(
current_processor: LogicalCpuId,
mapper: crate::paging::PageMapper,
) -> Self {
let ro = Self::lock_inner(current_processor.get() as usize);
Self {
mapper,
ro,
}
Self { mapper, ro }
}
pub fn lock_manually(current_processor: LogicalCpuId) -> Self {
unsafe { Self::lock_for_manual_mapper(current_processor, PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR)) }
unsafe {
Self::lock_for_manual_mapper(
current_processor,
PageMapper::current(TableKind::Kernel, FRAME_ALLOCATOR),
)
}
}
pub fn lock() -> Self {
Self::lock_manually(crate::cpu_id())
@@ -320,12 +316,18 @@ impl Drop for KernelMapper {
}
pub unsafe fn init(
kernel_base: usize, kernel_size: usize,
stack_base: usize, stack_size: usize,
env_base: usize, env_size: usize,
acpi_base: usize, acpi_size: usize,
areas_base: usize, areas_size: usize,
initfs_base: usize, initfs_size: usize,
kernel_base: usize,
kernel_size: usize,
stack_base: usize,
stack_size: usize,
env_base: usize,
env_size: usize,
acpi_base: usize,
acpi_size: usize,
areas_base: usize,
areas_size: usize,
initfs_base: usize,
initfs_size: usize,
) {
type A = RmmA;
@@ -333,24 +335,24 @@ pub unsafe fn init(
let real_size = 0x100000;
let real_end = real_base + real_size;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let kernel_end = kernel_base + kernel_size_aligned;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_size_aligned = ((stack_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let stack_end = stack_base + stack_size_aligned;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let env_size_aligned = ((env_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let env_end = env_base + env_size_aligned;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_size_aligned = ((acpi_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let acpi_end = acpi_base + acpi_size_aligned;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_size_aligned = ((initfs_size + (A::PAGE_SIZE - 1)) / A::PAGE_SIZE) * A::PAGE_SIZE;
let initfs_end = initfs_base + initfs_size_aligned;
let bootloader_areas = slice::from_raw_parts(
areas_base as *const BootloaderMemoryEntry,
areas_size / mem::size_of::<BootloaderMemoryEntry>()
areas_size / mem::size_of::<BootloaderMemoryEntry>(),
);
// Copy memory map from bootloader location, and page align it
@@ -383,44 +385,86 @@ pub unsafe fn init(
// Ensure real-mode areas are not used
if base < real_end && base + size > real_base {
log::warn!("{:X}:{:X} overlaps with real mode {:X}:{:X}", base, size, real_base, real_size);
log::warn!(
"{:X}:{:X} overlaps with real mode {:X}:{:X}",
base,
size,
real_base,
real_size
);
new_base = cmp::max(new_base, real_end);
}
// Ensure kernel areas are not used
if base < kernel_end && base + size > kernel_base {
log::warn!("{:X}:{:X} overlaps with kernel {:X}:{:X}", base, size, kernel_base, kernel_size);
log::warn!(
"{:X}:{:X} overlaps with kernel {:X}:{:X}",
base,
size,
kernel_base,
kernel_size
);
new_base = cmp::max(new_base, kernel_end);
}
// Ensure stack areas are not used
if base < stack_end && base + size > stack_base {
log::warn!("{:X}:{:X} overlaps with stack {:X}:{:X}", base, size, stack_base, stack_size);
log::warn!(
"{:X}:{:X} overlaps with stack {:X}:{:X}",
base,
size,
stack_base,
stack_size
);
new_base = cmp::max(new_base, stack_end);
}
// Ensure env areas are not used
if base < env_end && base + size > env_base {
log::warn!("{:X}:{:X} overlaps with env {:X}:{:X}", base, size, env_base, env_size);
log::warn!(
"{:X}:{:X} overlaps with env {:X}:{:X}",
base,
size,
env_base,
env_size
);
new_base = cmp::max(new_base, env_end);
}
// Ensure acpi areas are not used
if base < acpi_end && base + size > acpi_base {
log::warn!("{:X}:{:X} overlaps with acpi {:X}:{:X}", base, size, acpi_base, acpi_size);
log::warn!(
"{:X}:{:X} overlaps with acpi {:X}:{:X}",
base,
size,
acpi_base,
acpi_size
);
new_base = cmp::max(new_base, acpi_end);
}
// Ensure initfs areas are not used
if base < initfs_end && base + size > initfs_base {
log::warn!("{:X}:{:X} overlaps with initfs {:X}:{:X}", base, size, initfs_base, initfs_size);
log::warn!(
"{:X}:{:X} overlaps with initfs {:X}:{:X}",
base,
size,
initfs_base,
initfs_size
);
new_base = cmp::max(new_base, initfs_end);
}
if new_base != base {
let end = base + size;
let new_size = end.checked_sub(new_base).unwrap_or(0);
log::info!("{:X}:{:X} moved to {:X}:{:X}", base, size, new_base, new_size);
log::info!(
"{:X}:{:X} moved to {:X}:{:X}",
base,
size,
new_base,
new_size
);
base = new_base;
size = new_size;
}
@@ -439,11 +483,16 @@ pub unsafe fn init(
let allocator = inner::<A>(
areas(),
kernel_base, kernel_size_aligned,
stack_base, stack_size_aligned,
env_base, env_size_aligned,
acpi_base, acpi_size_aligned,
initfs_base, initfs_size_aligned,
kernel_base,
kernel_size_aligned,
stack_base,
stack_size_aligned,
env_base,
env_size_aligned,
acpi_base,
acpi_size_aligned,
initfs_base,
initfs_size_aligned,
);
*INNER_ALLOCATOR.lock() = Some(allocator);
}
+70 -31
View File
@@ -2,24 +2,22 @@
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, AtomicU32};
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
use crate::{allocator, memory, LogicalCpuId};
#[cfg(feature = "acpi")]
use crate::acpi;
use crate::arch::pti;
use crate::arch::flags::*;
use crate::device;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug;
use crate::gdt;
use crate::idt;
use crate::interrupt;
use crate::misc;
use crate::log::{self, info};
use crate::paging::{self, PhysicalAddress, RmmA, RmmArch, TableKind};
use crate::{
allocator,
arch::{flags::*, pti},
device, gdt, idt, interrupt,
log::{self, info},
memory, misc,
paging::{self, PhysicalAddress, RmmA, RmmArch, TableKind},
LogicalCpuId,
};
/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
@@ -68,7 +66,7 @@ pub struct KernelArgs {
/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
let bootstrap = {
let args = args_ptr.read();
@@ -82,7 +80,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
KERNEL_SIZE.store(args.kernel_size as usize, Ordering::SeqCst);
// Convert env to slice
let env = slice::from_raw_parts((args.env_base as usize + crate::PHYS_OFFSET) as *const u8, args.env_size as usize);
let env = slice::from_raw_parts(
(args.env_base as usize + crate::PHYS_OFFSET) as *const u8,
args.env_size as usize,
);
// Set up graphical debug
#[cfg(feature = "graphical_debug")]
@@ -104,12 +105,36 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
});
info!("Redox OS starting...");
info!("Kernel: {:X}:{:X}", { args.kernel_base }, { args.kernel_base } + { args.kernel_size });
info!("Stack: {:X}:{:X}", { args.stack_base }, { args.stack_base } + { args.stack_size });
info!("Env: {:X}:{:X}", { args.env_base }, { args.env_base } + { args.env_size });
info!("RSDPs: {:X}:{:X}", { args.acpi_rsdps_base }, { args.acpi_rsdps_base } + { args.acpi_rsdps_size });
info!("Areas: {:X}:{:X}", { args.areas_base }, { args.areas_base } + { args.areas_size });
info!("Bootstrap: {:X}:{:X}", { args.bootstrap_base }, { args.bootstrap_base } + { args.bootstrap_size });
info!(
"Kernel: {:X}:{:X}",
{ args.kernel_base },
{ args.kernel_base } + { args.kernel_size }
);
info!(
"Stack: {:X}:{:X}",
{ args.stack_base },
{ args.stack_base } + { args.stack_size }
);
info!(
"Env: {:X}:{:X}",
{ args.env_base },
{ args.env_base } + { args.env_size }
);
info!(
"RSDPs: {:X}:{:X}",
{ args.acpi_rsdps_base },
{ args.acpi_rsdps_base } + { args.acpi_rsdps_size }
);
info!(
"Areas: {:X}:{:X}",
{ args.areas_base },
{ args.areas_base } + { args.areas_size }
);
info!(
"Bootstrap: {:X}:{:X}",
{ args.bootstrap_base },
{ args.bootstrap_base } + { args.bootstrap_size }
);
info!("Bootstrap entry point: {:X}", { args.bootstrap_entry });
// Set up GDT before paging
@@ -120,19 +145,28 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Initialize RMM
crate::arch::rmm::init(
args.kernel_base as usize, args.kernel_size as usize,
args.stack_base as usize, args.stack_size as usize,
args.env_base as usize, args.env_size as usize,
args.acpi_rsdps_base as usize, args.acpi_rsdps_size as usize,
args.areas_base as usize, args.areas_size as usize,
args.bootstrap_base as usize, args.bootstrap_size as usize,
args.kernel_base as usize,
args.kernel_size as usize,
args.stack_base as usize,
args.stack_size as usize,
args.env_base as usize,
args.env_size as usize,
args.acpi_rsdps_base as usize,
args.acpi_rsdps_size as usize,
args.areas_base as usize,
args.areas_size as usize,
args.bootstrap_base as usize,
args.bootstrap_size as usize,
);
// Initialize PAT
paging::init();
// Set up GDT after paging with TLS
gdt::init_paging(args.stack_base as usize + args.stack_size as usize, LogicalCpuId::BSP);
gdt::init_paging(
args.stack_base as usize + args.stack_size as usize,
LogicalCpuId::BSP,
);
// Set up IDT
idt::init_paging_bsp();
@@ -172,7 +206,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
#[cfg(feature = "acpi")]
{
acpi::init(if args.acpi_rsdps_base != 0 && args.acpi_rsdps_size > 0 {
Some(((args.acpi_rsdps_base as usize + crate::PHYS_OFFSET) as u64, args.acpi_rsdps_size as u64))
Some((
(args.acpi_rsdps_base as usize + crate::PHYS_OFFSET) as u64,
args.acpi_rsdps_size as u64,
))
} else {
None
});
@@ -192,7 +229,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
BSP_READY.store(true, Ordering::SeqCst);
crate::Bootstrap {
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(args.bootstrap_base as usize)),
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(
args.bootstrap_base as usize,
)),
page_count: (args.bootstrap_size as usize) / crate::memory::PAGE_SIZE,
entry: args.bootstrap_entry as usize,
env,
@@ -213,7 +252,7 @@ pub struct KernelArgsAp {
}
/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
pub unsafe extern "C" fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
let cpu_id = {
let args = &*args_ptr;
let cpu_id = LogicalCpuId::new(args.cpu_id as u32);
@@ -259,7 +298,7 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
cpu_id
};
while ! BSP_READY.load(Ordering::SeqCst) {
while !BSP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
+9 -10
View File
@@ -1,14 +1,10 @@
#[cfg(feature = "acpi")]
use crate::{
context,
scheme::acpi,
time,
};
use crate::{context, scheme::acpi, time};
use crate::syscall::io::{Io, Pio};
#[no_mangle]
pub unsafe extern fn kreset() -> ! {
pub unsafe extern "C" fn kreset() -> ! {
println!("kreset");
// 8042 reset
@@ -24,11 +20,14 @@ pub unsafe extern fn kreset() -> ! {
pub unsafe fn emergency_reset() -> ! {
// Use triple fault to guarantee reset
core::arch::asm!("
core::arch::asm!(
"
cli
lidt cs:0
int $3
", options(noreturn));
",
options(noreturn)
);
}
#[cfg(feature = "acpi")]
@@ -36,7 +35,7 @@ fn userspace_acpi_shutdown() {
log::info!("Notifying any potential ACPI driver");
// Tell whatever driver that handles ACPI, that it should enter the S5 state (i.e.
// shutdown).
if ! acpi::register_kstop() {
if !acpi::register_kstop() {
// There was no context to switch to.
log::info!("No ACPI driver was alive to handle shutdown.");
return;
@@ -63,7 +62,7 @@ fn userspace_acpi_shutdown() {
}
#[no_mangle]
pub unsafe extern fn kstop() -> ! {
pub unsafe extern "C" fn kstop() -> ! {
log::info!("Running kstop()");
#[cfg(feature = "acpi")]
+24 -10
View File
@@ -1,8 +1,6 @@
use core::alloc::Layout;
use core::alloc::GlobalAlloc;
use core::alloc::{GlobalAlloc, Layout};
use crate::common::unique::Unique;
use crate::memory::Enomem;
use crate::{common::unique::Unique, memory::Enomem};
// Necessary because GlobalAlloc::dealloc requires the layout to be the same, and therefore Box
// cannot be used for increased alignment directly.
@@ -24,7 +22,11 @@ impl<T: ?Sized, const ALIGN: usize> AlignedBox<T, ALIGN> {
}
const fn layout_upgrade_align(layout: Layout, align: usize) -> Layout {
const fn max(a: usize, b: usize) -> usize {
if a > b { a } else { b }
if a > b {
a
} else {
b
}
}
let Ok(x) = Layout::from_size_align(layout.size(), max(align, layout.align())) else {
panic!("failed to calculate layout");
@@ -39,7 +41,8 @@ impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> {
T: ValidForZero,
{
Ok(unsafe {
let ptr = crate::ALLOCATOR.alloc_zeroed(layout_upgrade_align(Layout::new::<T>(), ALIGN));
let ptr =
crate::ALLOCATOR.alloc_zeroed(layout_upgrade_align(Layout::new::<T>(), ALIGN));
if ptr.is_null() {
return Err(Enomem);
}
@@ -56,7 +59,10 @@ impl<T, const ALIGN: usize> AlignedBox<[T], ALIGN> {
T: ValidForZero,
{
Ok(unsafe {
let ptr = crate::ALLOCATOR.alloc_zeroed(layout_upgrade_align(Layout::array::<T>(len).unwrap(), ALIGN));
let ptr = crate::ALLOCATOR.alloc_zeroed(layout_upgrade_align(
Layout::array::<T>(len).unwrap(),
ALIGN,
));
if ptr.is_null() {
return Err(Enomem);
}
@@ -69,7 +75,13 @@ impl<T, const ALIGN: usize> AlignedBox<[T], ALIGN> {
impl<T: ?Sized, const ALIGN: usize> core::fmt::Debug for AlignedBox<T, ALIGN> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "[aligned box at {:p}, size {} alignment {}]", self.inner.as_ptr(), self.layout().size(), self.layout().align())
write!(
f,
"[aligned box at {:p}, size {} alignment {}]",
self.inner.as_ptr(),
self.layout().size(),
self.layout().align()
)
}
}
impl<T: ?Sized, const ALIGN: usize> Drop for AlignedBox<T, ALIGN> {
@@ -95,14 +107,16 @@ impl<T: ?Sized, const ALIGN: usize> core::ops::DerefMut for AlignedBox<T, ALIGN>
}
impl<T: Clone + ValidForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN> {
fn clone(&self) -> Self {
let mut new = Self::try_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(self.layout()));
let mut new =
Self::try_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(self.layout()));
T::clone_from(&mut new, self);
new
}
}
impl<T: Clone + ValidForZero, const ALIGN: usize> Clone for AlignedBox<[T], ALIGN> {
fn clone(&self) -> Self {
let mut new = Self::try_zeroed_slice(self.len()).unwrap_or_else(|_| alloc::alloc::handle_alloc_error(self.layout()));
let mut new = Self::try_zeroed_slice(self.len())
.unwrap_or_else(|_| alloc::alloc::handle_alloc_error(self.layout()));
for i in 0..self.len() {
new[i].clone_from(&self[i]);
}

Some files were not shown because too many files have changed in this diff Show More