Refactor functions in vm module

This commit is contained in:
Yuke Peng 2023-03-21 21:32:50 -07:00 committed by Tate, Hongliang Tian
parent 8c7b5d84d1
commit 6e29996720
12 changed files with 110 additions and 78 deletions

View File

@ -1,6 +1,6 @@
use core::ptr::NonNull;
use crate::{config, vm::phys_to_virt};
use crate::{config, vm::paddr_to_vaddr};
use acpi::{AcpiHandler, AcpiTables};
use lazy_static::lazy_static;
use limine::LimineRsdpRequest;
@ -25,7 +25,7 @@ impl AcpiHandler for AcpiMemoryHandler {
) -> acpi::PhysicalMapping<Self, T> {
acpi::PhysicalMapping::new(
physical_address,
NonNull::new(phys_to_virt(physical_address) as *mut T).unwrap(),
NonNull::new(paddr_to_vaddr(physical_address) as *mut T).unwrap(),
size,
size,
self.clone(),

View File

@ -60,7 +60,7 @@ pub fn init() {
panic!("Unknown interrupt model")
}
};
let mut io_apic = unsafe { IoApic::new(crate::vm::phys_to_virt(ioapic_address as usize)) };
let mut io_apic = unsafe { IoApic::new(crate::vm::paddr_to_vaddr(ioapic_address as usize)) };
let id = io_apic.id();
let version = io_apic.version();

View File

@ -1,4 +1,4 @@
use crate::vm::phys_to_virt;
use crate::vm::paddr_to_vaddr;
use acpi::{AcpiError, HpetInfo};
use alloc::vec::Vec;
use spin::Once;
@ -36,14 +36,14 @@ struct Hpet {
impl Hpet {
fn new(base_address: usize) -> Hpet {
let information_register_ref = unsafe {
&*(phys_to_virt(base_address + OFFSET_ID_REGISTER) as *mut usize as *mut u32)
&*(paddr_to_vaddr(base_address + OFFSET_ID_REGISTER) as *mut usize as *mut u32)
};
let general_configuration_register_ref = unsafe {
&mut *(phys_to_virt(base_address + OFFSET_CONFIGURATION_REGISTER) as *mut usize
&mut *(paddr_to_vaddr(base_address + OFFSET_CONFIGURATION_REGISTER) as *mut usize
as *mut u32)
};
let general_interrupt_status_register_ref = unsafe {
&mut *(phys_to_virt(base_address + OFFSET_INTERRUPT_STATUS_REGISTER) as *mut usize
&mut *(paddr_to_vaddr(base_address + OFFSET_INTERRUPT_STATUS_REGISTER) as *mut usize
as *mut u32)
};
@ -58,7 +58,7 @@ impl Hpet {
for i in 0..num_comparator {
let comp = Volatile::new(unsafe {
&mut *(phys_to_virt(base_address + 0x100 + i as usize * 0x20) as *mut usize
&mut *(paddr_to_vaddr(base_address + 0x100 + i as usize * 0x20) as *mut usize
as *mut HpetTimerRegister)
});
comparators.push(comp);

View File

@ -47,7 +47,7 @@ pub(crate) fn has_apic() -> bool {
pub(crate) fn init() {
super::pic::disable_temp();
let mut apic = Xapic::new(vm::phys_to_virt(get_apic_base_address()));
let mut apic = Xapic::new(vm::paddr_to_vaddr(get_apic_base_address()));
// enable apic
set_apic_base_address(get_apic_base_address());

View File

@ -48,6 +48,10 @@ impl KernelStack {
)?,
})
}
pub fn end_paddr(&self) -> Paddr {
self.frame.get(self.frame.len() - 1).unwrap().end_paddr()
}
}
/// A task that executes a function to the end.
@ -132,7 +136,7 @@ impl Task {
result.task_inner.lock().task_status = TaskStatus::Runnable;
result.task_inner.lock().ctx.rip = kernel_task_entry as usize;
result.task_inner.lock().ctx.regs.rsp =
(crate::vm::phys_to_virt(result.kstack.frame.end_pa().unwrap())) as u64;
(crate::vm::paddr_to_vaddr(result.kstack.end_paddr())) as u64;
let arc_self = Arc::new(result);
switch_to_task(arc_self.clone());
@ -172,7 +176,7 @@ impl Task {
result.task_inner.lock().task_status = TaskStatus::Runnable;
result.task_inner.lock().ctx.rip = kernel_task_entry as usize;
result.task_inner.lock().ctx.regs.rsp =
(crate::vm::phys_to_virt(result.kstack.frame.end_pa().unwrap())) as u64;
(crate::vm::paddr_to_vaddr(result.kstack.end_paddr())) as u64;
Ok(Arc::new(result))
}

View File

@ -1,15 +1,15 @@
use alloc::vec;
use core::{
iter::Iterator,
ops::{BitAnd, BitOr, Not},
};
use crate::{config::PAGE_SIZE, prelude::*, Error};
use pod::Pod;
use super::{Paddr, VmIo};
use alloc::vec;
use super::frame_allocator;
use super::{Paddr, VmIo};
use pod::Pod;
/// A collection of page frames (physical memory pages).
///
@ -58,6 +58,10 @@ impl VmFrameVec {
Ok(Self(frame_list))
}
pub fn get(&self, index: usize) -> Option<&VmFrame> {
self.0.get(index)
}
/// returns an empty vmframe vec
pub fn empty() -> Self {
Self(Vec::new())
@ -68,15 +72,6 @@ impl VmFrameVec {
self.0.push(new_frame);
}
/// get the end pa of the collection
pub fn end_pa(&self) -> Option<Paddr> {
if let Some(frame) = self.0.last() {
Some(frame.start_pa() + PAGE_SIZE)
} else {
None
}
}
/// Pop a frame from the collection.
pub fn pop(&mut self) -> Option<VmFrame> {
self.0.pop()
@ -304,11 +299,11 @@ impl VmFrame {
}
/// Returns the physical address of the page frame.
pub fn start_pa(&self) -> Paddr {
pub fn start_paddr(&self) -> Paddr {
self.frame_index() * PAGE_SIZE
}
pub fn end_pa(&self) -> Paddr {
pub fn end_paddr(&self) -> Paddr {
(self.frame_index() + 1) * PAGE_SIZE
}
@ -316,7 +311,7 @@ impl VmFrame {
pub fn zero(&self) {
unsafe {
core::ptr::write_bytes(
super::phys_to_virt(self.start_pa()) as *mut u8,
super::paddr_to_vaddr(self.start_paddr()) as *mut u8,
0,
PAGE_SIZE,
)
@ -340,7 +335,10 @@ impl VmFrame {
}
pub unsafe fn as_slice(&self) -> &mut [u8] {
core::slice::from_raw_parts_mut(super::phys_to_virt(self.start_pa()) as *mut u8, PAGE_SIZE)
core::slice::from_raw_parts_mut(
super::paddr_to_vaddr(self.start_paddr()) as *mut u8,
PAGE_SIZE,
)
}
}
@ -367,15 +365,15 @@ impl VmIo for VmFrame {
/// Read a value of a specified type at a specified offset.
fn read_val<T: Pod>(&self, offset: usize) -> Result<T> {
let paddr = self.start_pa() + offset;
let val = unsafe { &mut *(super::phys_to_virt(paddr) as *mut T) };
let paddr = self.start_paddr() + offset;
let val = unsafe { &mut *(super::paddr_to_vaddr(paddr) as *mut T) };
Ok(*val)
}
/// Write a value of a specified type at a specified offset.
fn write_val<T: Pod>(&self, offset: usize, new_val: &T) -> Result<()> {
let paddr = self.start_pa() + offset;
unsafe { (super::phys_to_virt(paddr) as *mut T).write(*new_val) };
let paddr = self.start_paddr() + offset;
unsafe { (super::paddr_to_vaddr(paddr) as *mut T).write(*new_val) };
Ok(())
}
}

View File

@ -1,7 +1,9 @@
use core::ops::Range;
use alloc::vec::Vec;
use buddy_system_allocator::FrameAllocator;
use limine::{LimineMemmapEntry, LimineMemoryMapEntryType};
use log::info;
use log::{debug, info};
use spin::{Mutex, Once};
use crate::{config::PAGE_SIZE, vm::Paddr, AlignExt};
@ -40,7 +42,10 @@ pub fn alloc_continuous(frame_count: usize) -> Option<Vec<VmFrame>> {
}
pub fn alloc_with_paddr(paddr: Paddr) -> Option<VmFrame> {
// FIXME: need to check whether the physical address is invalid or not
if !is_paddr_valid(paddr..paddr + PAGE_SIZE) {
debug!("not a valid paddr:{:x}", paddr);
return None;
}
unsafe {
Some(VmFrame::new(
paddr.align_down(PAGE_SIZE),
@ -49,6 +54,29 @@ pub fn alloc_with_paddr(paddr: Paddr) -> Option<VmFrame> {
}
}
/// Check if the physical address in range is valid
fn is_paddr_valid(range: Range<usize>) -> bool {
// special area in x86
if range.start >= 0xFE00_0000 && range.end <= 0xFFFF_FFFF {
return true;
}
for i in super::MEMORY_REGIONS.get().unwrap().iter() {
match i.typ {
LimineMemoryMapEntryType::Usable => {}
LimineMemoryMapEntryType::Reserved => {}
LimineMemoryMapEntryType::Framebuffer => {}
_ => {
continue;
}
}
if range.start as u64 >= i.base && (range.end as u64) <= i.base + i.len {
return true;
}
}
false
}
pub(crate) fn alloc_zero() -> Option<VmFrame> {
let frame = alloc()?;
frame.zero();

View File

@ -82,7 +82,7 @@ impl MapArea {
match self.mapper.entry(va) {
Entry::Occupied(e) => panic!("already mapped a input physical address"),
Entry::Vacant(e) => e.insert(pa).start_pa(),
Entry::Vacant(e) => e.insert(pa).start_paddr(),
}
}
@ -90,8 +90,10 @@ impl MapArea {
assert!(is_page_aligned(va));
match self.mapper.entry(va) {
Entry::Occupied(e) => e.get().start_pa(),
Entry::Vacant(e) => e.insert(frame_allocator::alloc_zero().unwrap()).start_pa(),
Entry::Occupied(e) => e.get().start_paddr(),
Entry::Vacant(e) => e
.insert(frame_allocator::alloc_zero().unwrap())
.start_paddr(),
}
}

View File

@ -23,7 +23,7 @@ pub use self::space::{VmMapOptions, VmPerm, VmSpace};
pub use self::{
memory_set::{MapArea, MemorySet},
page_table::{translate_not_offset_virtual_address, PageTable},
page_table::PageTable,
};
use alloc::vec::Vec;
@ -31,12 +31,18 @@ use limine::LimineMemmapRequest;
use log::debug;
use spin::Once;
pub const fn phys_to_virt(pa: usize) -> usize {
/// Convert physical address to virtual address using offset, only available inside jinux-frame
pub(crate) fn paddr_to_vaddr(pa: usize) -> usize {
pa + PHYS_OFFSET
}
pub const fn virt_to_phys(va: usize) -> usize {
va - PHYS_OFFSET
pub fn vaddr_to_paddr(va: Vaddr) -> Option<Paddr> {
if va >= crate::config::PHYS_OFFSET && va <= crate::config::KERNEL_OFFSET {
// can use offset to get the physical address
Some(va - PHYS_OFFSET)
} else {
page_table::vaddr_to_paddr(va)
}
}
pub const fn is_page_aligned(p: usize) -> bool {

View File

@ -50,7 +50,7 @@ impl PageTableEntry {
pub const fn new_page(pa: Paddr, flags: PageTableFlags) -> Self {
Self((pa & Self::PHYS_ADDR_MASK) | flags.bits)
}
const fn pa(self) -> Paddr {
const fn paddr(self) -> Paddr {
self.0 as usize & Self::PHYS_ADDR_MASK
}
const fn flags(self) -> PageTableFlags {
@ -68,7 +68,7 @@ impl fmt::Debug for PageTableEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut f = f.debug_struct("PageTableEntry");
f.field("raw", &self.0)
.field("pa", &self.pa())
.field("paddr", &self.paddr())
.field("flags", &self.flags())
.finish()
}
@ -83,13 +83,13 @@ pub struct PageTable {
impl PageTable {
pub fn new() -> Self {
let root_frame = frame_allocator::alloc_zero().unwrap();
let p4 = table_of(root_frame.start_pa());
let p4 = table_of(root_frame.start_paddr()).unwrap();
let map_pte = ALL_MAPPED_PTE.lock();
for (index, pte) in map_pte.iter() {
p4[*index] = *pte;
}
Self {
root_pa: root_frame.start_pa(),
root_pa: root_frame.start_paddr(),
tables: vec![root_frame],
}
}
@ -124,8 +124,8 @@ impl PageTable {
pub fn map_area(&mut self, area: &MapArea) {
for (va, pa) in area.mapper.iter() {
assert!(pa.start_pa() < PHYS_OFFSET);
self.map(*va, pa.start_pa(), area.flags);
assert!(pa.start_paddr() < PHYS_OFFSET);
self.map(*va, pa.start_paddr(), area.flags);
}
}
@ -139,13 +139,13 @@ impl PageTable {
impl PageTable {
fn alloc_table(&mut self) -> Paddr {
let frame = frame_allocator::alloc_zero().unwrap();
let pa = frame.start_pa();
let pa = frame.start_paddr();
self.tables.push(frame);
pa
}
fn get_entry_or_create(&mut self, va: Vaddr) -> Option<&mut PageTableEntry> {
let p4 = table_of(self.root_pa);
let p4 = table_of(self.root_pa).unwrap();
let p4e = &mut p4[p4_index(va)];
let p3 = next_table_or_create(p4e, || self.alloc_table())?;
let p3e = &mut p3[p3_index(va)];
@ -174,7 +174,7 @@ const fn p1_index(va: Vaddr) -> usize {
}
fn get_entry(root_pa: Paddr, va: Vaddr) -> Option<&'static mut PageTableEntry> {
let p4 = table_of(root_pa);
let p4 = table_of(root_pa).unwrap();
let p4e = &mut p4[p4_index(va)];
let p3 = next_table(p4e)?;
let p3e = &mut p3[p3_index(va)];
@ -185,14 +185,17 @@ fn get_entry(root_pa: Paddr, va: Vaddr) -> Option<&'static mut PageTableEntry> {
Some(p1e)
}
fn table_of<'a>(pa: Paddr) -> &'a mut [PageTableEntry] {
let ptr = super::phys_to_virt(pa) as *mut _;
unsafe { core::slice::from_raw_parts_mut(ptr, ENTRY_COUNT) }
fn table_of<'a>(pa: Paddr) -> Option<&'a mut [PageTableEntry]> {
if pa == 0 {
return None;
}
let ptr = super::paddr_to_vaddr(pa) as *mut _;
unsafe { Some(core::slice::from_raw_parts_mut(ptr, ENTRY_COUNT)) }
}
fn next_table<'a>(entry: &PageTableEntry) -> Option<&'a mut [PageTableEntry]> {
if entry.is_present() {
Some(table_of(entry.pa()))
Some(table_of(entry.paddr()).unwrap())
} else {
None
}
@ -208,40 +211,37 @@ fn next_table_or_create<'a>(
pa,
PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER,
);
Some(table_of(pa))
Some(table_of(pa).unwrap())
} else {
next_table(entry)
}
}
/// translate a virtual address to physical address which cannot use offset to get physical address
/// Note: this may not useful for accessing usermode data, use offset first
pub fn translate_not_offset_virtual_address(address: usize) -> usize {
pub fn vaddr_to_paddr(virtual_address: Vaddr) -> Option<Paddr> {
let (cr3, _) = x86_64::registers::control::Cr3::read();
let cr3 = cr3.start_address().as_u64() as usize;
let p4 = table_of(cr3);
let virtual_address = address;
let p4 = table_of(cr3)?;
let pte = p4[p4_index(virtual_address)];
let p3 = table_of(pte.pa());
let p3 = table_of(pte.paddr())?;
let pte = p3[p3_index(virtual_address)];
let p2 = table_of(pte.pa());
let p2 = table_of(pte.paddr())?;
let pte = p2[p2_index(virtual_address)];
let p1 = table_of(pte.pa());
let p1 = table_of(pte.paddr())?;
let pte = p1[p1_index(virtual_address)];
(pte.pa() & ((1 << 48) - 1)) + (address & ((1 << 12) - 1))
Some((pte.paddr() & ((1 << 48) - 1)) + (virtual_address & ((1 << 12) - 1)))
}
pub(crate) fn init() {
let (cr3, _) = x86_64::registers::control::Cr3::read();
let cr3 = cr3.start_address().as_u64() as usize;
let p4 = table_of(cr3);
let p4 = table_of(cr3).unwrap();
// Cancel mapping in lowest addresses.
p4[0].0 = 0;
let mut map_pte = ALL_MAPPED_PTE.lock();

View File

@ -96,7 +96,7 @@ impl VirtQueue {
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_desc),
frame.start_pa() as u64,
frame.start_paddr() as u64,
);
debug!("queue_desc vm frame:{:x?}", frame);
frame_vec.push(frame);
@ -108,7 +108,7 @@ impl VirtQueue {
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_driver),
frame.start_pa() as u64,
frame.start_paddr() as u64,
);
debug!("queue_driver vm frame:{:x?}", frame);
frame_vec.push(frame);
@ -120,7 +120,7 @@ impl VirtQueue {
.remove(0);
cfg.write_at(
offset_of!(VitrioPciCommonCfg, queue_device),
frame.start_pa() as u64,
frame.start_paddr() as u64,
);
debug!("queue_device vm frame:{:x?}", frame);
frame_vec.push(frame);
@ -337,8 +337,7 @@ struct Descriptor {
impl Descriptor {
fn set_buf(&mut self, buf: &[u8]) {
self.addr =
jinux_frame::vm::translate_not_offset_virtual_address(buf.as_ptr() as usize) as u64;
self.addr = jinux_frame::vm::vaddr_to_paddr(buf.as_ptr() as usize).unwrap() as u64;
self.len = buf.len() as u32;
}
@ -346,12 +345,7 @@ impl Descriptor {
fn set_buf(inframe_ptr: &InFramePtr<Descriptor>, buf: &[u8]) {
let va = buf.as_ptr() as usize;
let pa = if va >= jinux_frame::config::PHYS_OFFSET && va <= jinux_frame::config::KERNEL_OFFSET {
// can use offset
jinux_frame::vm::virt_to_phys(va)
} else {
jinux_frame::vm::translate_not_offset_virtual_address(buf.as_ptr() as usize)
};
let pa = jinux_frame::vm::vaddr_to_paddr(va).unwrap();
debug!("set buf write virt address:{:x}", va);
debug!("set buf write phys address:{:x}", pa);
inframe_ptr.write_at(offset_of!(Descriptor, addr), pa as u64);

View File

@ -24,7 +24,7 @@ impl<T: Pod> InFramePtr<T> {
options.paddr(Some(page_paddr));
VmFrameVec::allocate(&options)?.remove(0)
};
let offset = paddr - frame.start_pa();
let offset = paddr - frame.start_paddr();
Ok(Self {
frame,
offset,
@ -49,6 +49,6 @@ impl<T: Pod> InFramePtr<T> {
}
pub fn paddr(&self) -> usize {
self.offset + self.frame.start_pa()
self.offset + self.frame.start_paddr()
}
}