Skip to content

Commit

Permalink
Stage32: paging setup, but still faulting
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Dec 1, 2024
1 parent 85018bb commit c8cae5c
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 31 deletions.
2 changes: 2 additions & 0 deletions bootloader/stage-32bit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,6 @@ fn main(stage_to_stage: &Stage16toStage32) {
framebuffer.draw_glyph(10, 10, 'Q', Color::WHITE);
framebuffer.draw_glyph(20, 10, 'O', Color::WHITE);
framebuffer.draw_glyph(30, 10, 'S', Color::WHITE);

unsafe { paging::enable_paging() };
}
51 changes: 38 additions & 13 deletions bootloader/stage-32bit/src/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,49 +24,74 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
*/

use arch::{
paging64::{PageEntry1G, PageMapLvl4},
paging64::{
Lvl2Entry, PageEntry2M, PageEntryLvl3, PageEntryLvl4, PageMapLvl2, PageMapLvl3, PageMapLvl4,
},
registers::{cr0, cr3, cr4, ia32_efer, Segment, SegmentRegisters},
CpuPrivilege,
};
use core::cell::SyncUnsafeCell;
use lldebug::{print, println};
use util::consts::GIB;
use util::consts::{GIB, MIB};

/// Amount of Gib to identity map
const IDMAP_GIG_AMOUNT: usize = 8;
const IDMAP_GIG_AMOUNT: usize = 1;

static TABLE_LVL4: SyncUnsafeCell<PageMapLvl4> = SyncUnsafeCell::new(PageMapLvl4::new());
static TABLE_LVL3: SyncUnsafeCell<PageMapLvl3> = SyncUnsafeCell::new(PageMapLvl3::new());
static TABLE_LVL2: SyncUnsafeCell<[PageMapLvl2; IDMAP_GIG_AMOUNT]> =
SyncUnsafeCell::new([PageMapLvl2::new(); IDMAP_GIG_AMOUNT]);

pub fn identity_map() {
for gig in 0..IDMAP_GIG_AMOUNT {
let v_addr = gig * GIB;
let table_ptr = unsafe { &raw mut (*TABLE_LVL2.get())[gig] };

let lvl3 = PageEntry1G::new()
for mb2 in 0..2 {
let phy_addr = (mb2 as u64 * 2 * (MIB as u64)) + (gig as u64 * (GIB as u64));

let lvl2_entry = PageEntry2M::new()
.set_present_flag(true)
.set_read_write_flag(true)
.set_phy_address(phy_addr);

println!("{:064b}", lvl2_entry.into_raw());

unsafe { (*table_ptr).store(lvl2_entry, mb2) };
}

let lvl3_entry = PageEntryLvl3::new()
.set_present_flag(true)
.set_read_write_flag(true)
.set_execute_disable_flag(true)
.set_user_accessed_flag(false)
.set_virt_address(v_addr as u32);
.set_next_entry_phy_address(unsafe { (*table_ptr).table_ptr() });

unsafe {
(*TABLE_LVL4.get()).store(lvl3, gig);
}
unsafe { (*TABLE_LVL3.get()).store(lvl3_entry, gig) };
}

let lvl4_entry = PageEntryLvl4::new()
.set_present_flag(true)
.set_read_write_flag(true)
.set_next_entry_phy_address(unsafe { (*TABLE_LVL3.get()).table_ptr() });

unsafe { (*TABLE_LVL4.get()).store(lvl4_entry, 0) };
}

pub unsafe fn set_page_base_reg() {
let phy_addr = TABLE_LVL4.get() as u64;
let phy_addr = unsafe { (*TABLE_LVL4.get()).table_ptr() };

cr3::set_page_directory_base_register(phy_addr);
}

pub unsafe fn enable_paging() {
print!("Identity Mapping Regions...");
identity_map();
println!("OK");

print!("Setting Paging Base Register...");
set_page_base_reg();
println!("OK");

print!("Disabling Paging...");
cr0::set_paging_flag(true);
cr0::set_paging_flag(false);
println!("OK");

print!("Setting PAE...");
Expand Down
72 changes: 57 additions & 15 deletions crates/arch/src/paging64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub const MAX_PHY_MEMORY_WIDTH: usize = 48;
field(RW, 6, pub dirty),
field(RW, 7, pub page_attribute_table),
field(RW, 8, pub global),
field(RW, 12..48, pub virt_address),
field(RWNS, 12..48, pub phy_address),
field(RW, 59..62, pub protection_key),
field(RW, 63, pub execute_disable)
)]
Expand Down Expand Up @@ -67,7 +67,7 @@ impl PageEntry4K {
field(RW, 7, pub page_size),
field(RW, 8, pub global),
field(RW, 12, pub page_attribute_table),
field(RW, 21..48, pub virt_address),
field(RWNS, 21..48, pub phy_address),
field(RW, 59..62, pub protection_key),
field(RW, 63, pub execute_disable)
)]
Expand Down Expand Up @@ -96,7 +96,7 @@ impl PageEntry2M {
field(RW, 7, pub page_size),
field(RW, 8, pub global),
field(RW, 12, pub page_attribute_table),
field(RW, 21..48, pub virt_address),
field(RWNS, 21..48, pub phy_address),
field(RW, 59..62, pub protection_key),
field(RW, 63, pub execute_disable)
)]
Expand Down Expand Up @@ -277,22 +277,26 @@ impl PageEntryLvl5 {
}
}

#[repr(align(4096))]
#[repr(C, align(4096))]
#[derive(Clone, Copy)]
pub struct PageMapLvl5([u64; 512]);

#[repr(align(4096))]
#[repr(C, align(4096))]
#[derive(Clone, Copy)]
pub struct PageMapLvl4([u64; 512]);

#[repr(align(4096))]
#[repr(C, align(4096))]
#[derive(Clone, Copy)]
pub struct PageMapLvl3([u64; 512]);

#[repr(align(4096))]
#[repr(C, align(4096))]
#[derive(Clone, Copy)]
pub struct PageMapLvl2([u64; 512]);

#[repr(C, align(4096))]
#[derive(Clone, Copy)]
pub struct PageMapLvl1([u64; 512]);

// TODO: Make docs for these
// Theses are the entires that can fit into the tables
pub trait Lvl5Entry {
Expand All @@ -315,12 +319,6 @@ impl Lvl4Entry for PageEntryLvl4 {
}
}

impl Lvl4Entry for PageEntry1G {
fn into_raw(self) -> u64 {
self.0
}
}

pub trait Lvl3Entry {
fn into_raw(self) -> u64;
}
Expand All @@ -331,7 +329,7 @@ impl Lvl3Entry for PageEntryLvl3 {
}
}

impl Lvl3Entry for PageEntry2M {
impl Lvl3Entry for PageEntry1G {
fn into_raw(self) -> u64 {
self.0
}
Expand All @@ -347,12 +345,40 @@ impl Lvl2Entry for PageEntryLvl2 {
}
}

impl Lvl2Entry for PageEntry4K {
impl Lvl2Entry for PageEntry2M {
fn into_raw(self) -> u64 {
self.0
}
}

pub trait Lvl1Entry {
fn into_raw(self) -> u64;
}

impl Lvl1Entry for PageEntry4K {
fn into_raw(self) -> u64 {
self.0
}
}

impl PageMapLvl1 {
pub const fn new() -> Self {
Self([0; 512])
}

pub fn store(&mut self, entry: impl Lvl1Entry, index: usize) {
self.0[index] = entry.into_raw();
}

pub fn flood_table(&mut self, entry: impl Lvl1Entry) {
self.0 = [entry.into_raw(); 512];
}

pub fn table_ptr(&self) -> u64 {
self.0.as_ptr() as u64
}
}

impl PageMapLvl2 {
pub const fn new() -> Self {
Self([0; 512])
Expand All @@ -365,6 +391,10 @@ impl PageMapLvl2 {
pub fn flood_table(&mut self, entry: impl Lvl2Entry) {
self.0 = [entry.into_raw(); 512];
}

pub fn table_ptr(&self) -> u64 {
self.0.as_ptr() as u64
}
}

impl PageMapLvl3 {
Expand All @@ -379,6 +409,10 @@ impl PageMapLvl3 {
pub fn flood_table(&mut self, entry: impl Lvl3Entry) {
self.0 = [entry.into_raw(); 512];
}

pub fn table_ptr(&self) -> u64 {
self.0.as_ptr() as u64
}
}

impl PageMapLvl4 {
Expand All @@ -393,6 +427,10 @@ impl PageMapLvl4 {
pub fn flood_table(&mut self, entry: impl Lvl4Entry) {
self.0 = [entry.into_raw(); 512];
}

pub fn table_ptr(&self) -> u64 {
self.0.as_ptr() as u64
}
}

impl PageMapLvl5 {
Expand All @@ -407,5 +445,9 @@ impl PageMapLvl5 {
pub fn flood_table(&mut self, entry: impl Lvl5Entry) {
self.0 = [entry.into_raw(); 512];
}

pub fn table_ptr(&self) -> u64 {
self.0.as_ptr() as u64
}
}

2 changes: 1 addition & 1 deletion crates/arch/src/registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pub mod cr0 {
#[make_hw(
field(RW, 3, pub page_level_write_through),
field(RW, 4, pub page_level_cache_disable),
field(RW, 12..=63, pub page_directory_base_register)
field(RWNS, 12..=63, pub page_directory_base_register)
)]
pub mod cr3 {
#[inline(always)]
Expand Down
35 changes: 34 additions & 1 deletion crates/hw-macro/src/macro_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub struct GenInfo<'a> {
pub bit_offset: usize,
pub bit_amount: usize,
pub bit_mask: u64,
pub no_shift: bool,
pub vis: Visibility,
pub function_ident: Ident,
pub carry_self: bool,
Expand Down Expand Up @@ -132,6 +133,23 @@ impl<'a> Fields<'a> {
// Write
#write_value;

// Post Gen
#post_gen_tokens
}});
} else if gen_info.no_shift {
tokens.push(quote! {{
assert!(value & !(#bit_mask as #inner_type) == 0);

// Read
#read_value;

// Modify
let write_value =
(read_value & !(#bit_mask as #inner_type)) | (value as #inner_type);

// Write
#write_value;

// Post Gen
#post_gen_tokens
}});
Expand Down Expand Up @@ -208,6 +226,14 @@ impl<'a> Fields<'a> {
read_value & (1 << #bit_offset) != 0

}});
} else if gen_info.no_shift {
tokens.push(quote! {{
// Read
#read_value;

// Pull out value
(read_value & (#bit_mask as #inner_type)) as #output_type
}});
} else {
tokens.push(quote! {{
// Read
Expand Down Expand Up @@ -254,6 +280,11 @@ impl<'a> Fields<'a> {
(Access::RW, Bits::Single(_)) => ("is_", "_set", "set_", "_flag"),
(Access::RW, Bits::Range(_)) => ("get_", "", "set_", ""),

(Access::RWNS, Bits::Single(_)) => {
panic!("RWNS is not supported for single bit operations")
}
(Access::RWNS, Bits::Range(_)) => ("get_", "", "set_", ""),

(Access::RO, Bits::Single(_)) => ("is_", "_set", "", ""),
(Access::RO, Bits::Range(_)) => ("read_", "", "", ""),

Expand All @@ -262,7 +293,7 @@ impl<'a> Fields<'a> {
};

let default_type = self.default_type();
let function_type: TokenStream = field.type_to_fit(default_type).into();
let function_type: TokenStream = field.type_to_fit(&field.access, default_type).into();

let bit_offset = field.bit_offset();
let bit_amount = field.bit_amount(default_type);
Expand Down Expand Up @@ -298,6 +329,7 @@ impl<'a> Fields<'a> {
bit_offset,
bit_amount,
bit_mask,
no_shift: matches!(&field.access, Access::RWNS),
vis: field.vis.clone(),
function_ident: read_ident,
carry_self: false,
Expand Down Expand Up @@ -338,6 +370,7 @@ impl<'a> Fields<'a> {
bit_offset,
bit_amount,
bit_mask,
no_shift: matches!(&field.access, Access::RWNS),
vis: field.vis.clone(),
function_ident: write_ident,
carry_self: write_meta.carry_self,
Expand Down
12 changes: 11 additions & 1 deletion crates/hw-macro/src/make_hw_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ impl<'a> Into<BitFieldType> for &'a Type {

impl BitField {
/// The type required to fit the amount of bits desired.
pub fn type_to_fit(&self, default_type: BitFieldType) -> BitFieldType {
pub fn type_to_fit(&self, access: &Access, default_type: BitFieldType) -> BitFieldType {
if matches!(access, Access::RWNS) {
return default_type;
}

match self.bit_amount(default_type) {
1 => BitFieldType::TypeBool,
..=8 => BitFieldType::Type8,
Expand Down Expand Up @@ -230,6 +234,8 @@ pub enum Access {
WO,
RW1C,
RW1O,
/// Read/Write No Shift
RWNS,
}

mod access {
Expand All @@ -238,6 +244,7 @@ mod access {
syn::custom_keyword!(WO);
syn::custom_keyword!(RW1C);
syn::custom_keyword!(RW1O);
syn::custom_keyword!(RWNS);
}

impl Parse for Access {
Expand All @@ -259,6 +266,9 @@ impl Parse for Access {
} else if lookahead.peek(access::RW1O) {
input.parse::<access::RW1O>()?;
Ok(Access::RW1O)
} else if lookahead.peek(access::RWNS) {
input.parse::<access::RWNS>()?;
Ok(Access::RWNS)
} else {
Err(lookahead.error())
}
Expand Down

0 comments on commit c8cae5c

Please sign in to comment.