Skip to content

Commit

Permalink
Mem: Fix deadlock (should change page tables later)
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 15, 2025
1 parent 75fb7c6 commit b593abb
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 88 deletions.
7 changes: 4 additions & 3 deletions crates/mem/src/vmm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,12 @@ pub struct VmProcess {

impl VmProcess {
pub unsafe fn new_from_bootloader() -> Self {
let page_table = unsafe { page::SharedTable::new_from_bootloader() };
unsafe { page_table.load().unwrap() };

Self {
objects: RwLock::new(Vec::new()),
page_table: unsafe { page::SharedTable::new_from_bootloader() },
page_table,
}
}

Expand Down Expand Up @@ -307,9 +310,7 @@ impl VmProcess {
}
}

logln!("{}", self.page_table);
unsafe { self.page_table.load()? };
logln!("{}", self.page_table);

for b_obj in objects.iter_mut() {
let vm_region = b_obj.object.vm_region();
Expand Down
143 changes: 59 additions & 84 deletions crates/mem/src/vmm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use arch::paging64::{
PageEntry1G, PageEntry2M, PageEntry4K, PageEntryLvl2, PageEntryLvl3, PageEntryLvl4,
PageMapLvl1, PageMapLvl2, PageMapLvl3, PageMapLvl4,
};
use lldebug::logln;

Check warning on line 37 in crates/mem/src/vmm/page.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused import: `lldebug::logln`
use spin::RwLock;
use util::consts::{PAGE_1G, PAGE_2M, PAGE_4K};

Expand All @@ -42,7 +43,7 @@ static CURRENTLY_LOADED_TABLE: SharedTable = SharedTable::empty();
pub fn virt_to_phys(virt: u64) -> Option<u64> {
match CURRENTLY_LOADED_TABLE.virt_to_phys(virt) {
Ok(virt) => Some(virt),
Err(MemoryError::EmptySegment) | Err(MemoryError::AlreadyUsed) => {
Err(MemoryError::EmptySegment) => {
// FIXME: This is just hardcoded for now, but should be populated from the bootloader!!!!
//
// Since we know the bootloader is identity mapped, the physical PTRs are valid virtual PTRs!
Expand Down Expand Up @@ -174,23 +175,23 @@ impl SharedTable {
match &*lvl4 {
SharedState::NotPresent => Err(MemoryError::EmptySegment),
SharedState::OwnedTable(rw_lock) | SharedState::RefTable(rw_lock) => {
let lvl4 = rw_lock.read();
let lvl4 = unsafe { &mut *rw_lock.as_mut_ptr() };
let shared_state = &lvl4.vm_table[lvl4_index];
match shared_state {
SharedState::NotPresent => Err(MemoryError::NotFound),
SharedState::OwnedTable(rw_lock) | SharedState::RefTable(rw_lock) => {
let lvl3 = rw_lock.read();
let lvl3 = unsafe { &mut *rw_lock.as_mut_ptr() };
let shared_state = &lvl3.vm_table[lvl3_index];
match shared_state {
SharedState::NotPresent => Err(MemoryError::NotFound),
SharedState::OwnedTable(rw_lock) | SharedState::RefTable(rw_lock) => {
let lvl2 = rw_lock.read();
let lvl2 = unsafe { &mut *rw_lock.as_mut_ptr() };
let shared_state = &lvl2.vm_table[lvl2_index];
match shared_state {
SharedState::NotPresent => Err(MemoryError::NotFound),
SharedState::OwnedTable(rw_lock)
| SharedState::RefTable(rw_lock) => {
let lvl1 = rw_lock.read();
let lvl1 = unsafe { &mut *rw_lock.as_mut_ptr() };
let shared_state = lvl1.phys_table.get(lvl1_index);

if shared_state.is_present_set() {
Expand Down Expand Up @@ -225,13 +226,14 @@ impl SharedTable {
return Ok(());
}

match self.state.read().clone() {
let new_state = (&*self.state.read()).clone();
match new_state {
SharedState::RefTable(our_table) | SharedState::OwnedTable(our_table) => {
let mut global_table = CURRENTLY_LOADED_TABLE.state.write();

let table_vptr = our_table.read().phys_table.table_ptr();
let phys_ptr = virt_to_phys(table_vptr).ok_or(MemoryError::InvalidPageTable)?;

let mut global_table = CURRENTLY_LOADED_TABLE.state.write();

*global_table = SharedState::RefTable(our_table);
unsafe { arch::registers::cr3::set_page_directory_base_register(phys_ptr) };

Expand Down Expand Up @@ -380,9 +382,9 @@ impl SharedTable {
lvl2_entry.add_permissions_from(permissions);

lvl1.link_page(vpage, ppage, permissions);
})
})
})
});
});
});
});

Ok(())
Expand Down Expand Up @@ -535,19 +537,21 @@ impl SharedLvl4 {

let mut writeable = new_entry.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
}
SharedState::OwnedTable(ref rw_lock) => {
let mut writeable = rw_lock.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
Expand All @@ -562,9 +566,10 @@ impl SharedLvl4 {
}));

let ret = func(&mut *writeable.write(), &mut entry);
let write_ptr = writeable.read().phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.read().phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

self.vm_table[index] = SharedState::OwnedTable(writeable);
Expand Down Expand Up @@ -593,27 +598,6 @@ impl SharedLvl3 {
}
}

fn upgrade_entry(&mut self, entry: usize) {
let state = &mut self.vm_table[entry];

match state {
SharedState::NotPresent => {
// Make a new table
*state = SharedState::OwnedTable(Arc::new(RwLock::new(SharedLvl2::new())));
}
SharedState::RefTable(rw_lock) => {
let table = rw_lock.clone();
let inner_table = table.read();

*state = SharedState::OwnedTable(Arc::new(RwLock::new(SharedLvl2 {
phys_table: inner_table.phys_table.clone(),
vm_table: inner_table.vm_table.clone(),
})));
}
_ => (),
}
}

/// Gets a refrence to the inner structure, but does not upgrade it.
pub fn _inner_ref<F, R>(&self, index: usize, func: F) -> R
where
Expand Down Expand Up @@ -668,37 +652,43 @@ impl SharedLvl3 {

let mut writeable = new_entry.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
}
SharedState::OwnedTable(ref rw_lock) => {
let mut writeable = rw_lock.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
}
SharedState::RefTable(_) => {
self.upgrade_entry(index);
SharedState::RefTable(ref rw_lock) => {
let table = rw_lock.clone();
let inner_table = table.read();

let writeable = Arc::new(RwLock::new(SharedLvl2 {
phys_table: inner_table.phys_table.clone(),
vm_table: inner_table.vm_table.clone(),
}));

let SharedState::OwnedTable(ref table) = self.vm_table[index] else {
panic!("Upgraded table, but table is not owned!");
};
let ret = func(&mut *writeable.write(), &mut entry);
let write_ptr = writeable.read().phys_table.table_ptr();

let mut writeable = table.write();
let ret = func(&mut *writeable, &mut entry);
entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

self.vm_table[index] = SharedState::OwnedTable(writeable);

ret
}
};
Expand All @@ -720,26 +710,6 @@ impl SharedLvl2 {
}
}

fn upgrade_entry(&mut self, entry: usize) {
let state = &mut self.vm_table[entry];

match state {
SharedState::NotPresent => {
// Make a new table
*state = SharedState::OwnedTable(Arc::new(RwLock::new(SharedLvl1::new())));
}
SharedState::RefTable(rw_lock) => {
let table = rw_lock.clone();
let inner_table = table.read();

*state = SharedState::OwnedTable(Arc::new(RwLock::new(SharedLvl1 {
phys_table: inner_table.phys_table.clone(),
})));
}
_ => (),
}
}

/// Gets a refrence to the inner structure, but does not upgrade it.
pub fn _inner_ref<F, R>(&self, index: usize, func: F) -> R
where
Expand Down Expand Up @@ -795,37 +765,42 @@ impl SharedLvl2 {

let mut writeable = new_entry.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
}
SharedState::OwnedTable(ref rw_lock) => {
let mut writeable = rw_lock.write();
let ret = func(&mut *writeable, &mut entry);
let write_ptr = writeable.phys_table.table_ptr();

entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

ret
}
SharedState::RefTable(_) => {
self.upgrade_entry(index);
SharedState::RefTable(ref rw_lock) => {
let table = rw_lock.clone();
let inner_table = table.read();

let SharedState::OwnedTable(ref table) = self.vm_table[index] else {
panic!("Upgraded table, but table is not owned!");
};
let writeable = Arc::new(RwLock::new(SharedLvl1 {
phys_table: inner_table.phys_table.clone(),
}));

let ret = func(&mut *writeable.write(), &mut entry);
let write_ptr = writeable.read().phys_table.table_ptr();

let mut writeable = table.write();
let ret = func(&mut *writeable, &mut entry);
entry.set_next_entry_phy_address(
virt_to_phys(writeable.phys_table.table_ptr())
.expect("Cannot locate the physical ptr of page table!"),
virt_to_phys(write_ptr).expect("Cannot locate the physical ptr of page table!"),
);

self.vm_table[index] = SharedState::OwnedTable(writeable);

ret
}
};
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#![feature(abi_x86_interrupt)]
#![feature(allocator_api)]

mod gdt;

Check failure on line 32 in kernel/src/main.rs

View workflow job for this annotation

GitHub Actions / Build OS

file not found for module `gdt`
mod int;
mod panic;
mod scheduler;
Expand Down Expand Up @@ -73,6 +74,7 @@ fn main(kbh: &KernelBootHeader) {
HumanBytes::from(kbh.phys_mem_map.bytes_of(mem::phys::PhysMemoryKind::Free))
);

gdt::init_kernel_gdt();
int::attach_interrupts();
int::enable_pic();
timer::init_timer();
Expand Down
1 change: 0 additions & 1 deletion kernel/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ impl Scheduler {
VmPermissions::WRITE | VmPermissions::READ | VmPermissions::USER | VmPermissions::EXEC,
elf_owned,
));
logln!("Begining map");

process.map_all_now()
}
Expand Down

0 comments on commit b593abb

Please sign in to comment.