Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/arch/aarch64/ivc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl From<&HvIvcConfig> for IvcRecord {
}

impl Zone {
pub fn ivc_init(&mut self, ivc_configs: &[HvIvcConfig]) {
pub fn ivc_init(&mut self, ivc_configs: &[HvIvcConfig]) -> HvResult {
let mut inner = self.write();
for ivc_config in ivc_configs {
// is_new is ok to remove
Expand All @@ -170,8 +170,7 @@ impl Zone {
start_paddr,
rw_sec_size as _,
MemFlags::READ | MemFlags::WRITE,
))
.unwrap();
))?;
for i in 0..ivc_config.max_peers as usize {
let flags = if i == ivc_config.peer_id as _ {
MemFlags::READ | MemFlags::WRITE
Expand All @@ -185,8 +184,7 @@ impl Zone {
start_paddr + rw_sec_size + i * out_sec_size,
out_sec_size as _,
flags,
))
.unwrap();
))?;
}
inner.mmio_region_register(
ivc_config.control_table_ipa as _,
Expand All @@ -195,12 +193,15 @@ impl Zone {
ivc_config.control_table_ipa as _,
);
} else {
return;
return hv_result_err!(EINVAL);
}
}

IVC_INFOS
.lock()
.insert(self.id(), IvcInfo::from(ivc_configs));

Ok(())
}
}

Expand Down
54 changes: 37 additions & 17 deletions src/arch/aarch64/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,19 +346,19 @@ where
Ok(p1e)
}

fn map_page(
&mut self,
page: Page<VA>,
paddr: PhysAddr,
flags: MemFlags,
) -> PagingResult<&mut PTE> {
let entry: &mut PTE = self.get_entry_mut_or_create(page)?;
fn map_page(&mut self, page: Page<VA>, paddr: PhysAddr, flags: MemFlags) -> PagingResult {
// Record the number of intermediate tables before allocation to enable rollback on failure.
let intrm_tables_len_before = self.intrm_tables.len();

let entry = self.get_entry_mut_or_create(page)?;
if !entry.is_unused() {
// Rollback before returning error (entry ref goes out of scope here).
self.intrm_tables.truncate(intrm_tables_len_before);
return Err(PagingError::AlreadyMapped);
}
entry.set_addr(page.size.align_down(paddr));
entry.set_flags(flags, page.size.is_huge());
Ok(entry)
Ok(())
}

fn unmap_page(&mut self, vaddr: VA) -> PagingResult<(PhysAddr, PageSize)> {
Expand Down Expand Up @@ -473,6 +473,7 @@ where
let _lock = self.clonee_lock.lock();
let mut vaddr = region.start.into();
let mut size = region.size;
let mut mapped_size = 0usize;
while size > 0 {
let paddr = region.mapper.map_fn(vaddr);
let page_size = if PageSize::Size1G.is_aligned(vaddr)
Expand All @@ -491,15 +492,34 @@ where
PageSize::Size4K
};
let page = Page::new_aligned(vaddr.into(), page_size);
self.inner
.map_page(page, paddr, region.flags)
.map_err(|e: PagingError| {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, e
);
e
})?;
if let Err(map_err) = self.inner.map_page(page, paddr, region.flags) {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, map_err
);
let mut rollback_vaddr = region.start.into();
let mut rollback_size = mapped_size;
while rollback_size > 0 {
let (_, rollback_page_size) =
self.inner.unmap_page(rollback_vaddr.into()).map_err(|rollback_err| {
error!(
"failed to rollback mapped page: {:#x?}, rollback error: {:?}, original map error: {:?}",
rollback_vaddr, rollback_err, map_err
);
rollback_err
})?;
if !rollback_page_size.is_aligned(rollback_vaddr) {
error!("rollback alignment error vaddr={:#x?}", rollback_vaddr);
loop {}
}
assert!(rollback_page_size.is_aligned(rollback_vaddr));
assert!(rollback_page_size as usize <= rollback_size);
rollback_vaddr += rollback_page_size as usize;
rollback_size -= rollback_page_size as usize;
}
return Err(map_err.into());
}
mapped_size += page_size as usize;
vaddr += page_size as usize;
size -= page_size as usize;
}
Expand Down
6 changes: 3 additions & 3 deletions src/arch/aarch64/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ impl Zone {
}

pub fn arch_zone_pre_configuration(&mut self, config: &HvZoneConfig) -> HvResult {
self.ivc_init(config.ivc_config());
Ok(())
self.ivc_init(config.ivc_config())
}

pub fn arch_zone_post_configuration(&mut self, _config: &HvZoneConfig) -> HvResult {
Expand All @@ -147,7 +146,8 @@ impl Zone {
let ctr_el0: u64;
core::arch::asm!("mrs {0}, ctr_el0", out(reg) ctr_el0, options(nostack, preserves_flags));
let dcache_line_size = (1 << ((ctr_el0 >> 16 & 0xF) as usize)) * 4;
self.gpm.for_each_region(|region| {
let inner = self.read();
inner.gpm().for_each_region(|region| {
// Invalidate all RAM regions of the guest
if !region.flags.contains(MemFlags::IO) { // TODO: need to enrich the types and exercise more precise control
// Calculate the physical start address of the region
Expand Down
56 changes: 39 additions & 17 deletions src/arch/loongarch64/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,21 +357,23 @@ where
Ok(p1e)
}

fn map_page(
&mut self,
page: Page<VA>,
paddr: PhysAddr,
flags: MemFlags,
) -> PagingResult<&mut PTE> {
fn map_page(&mut self, page: Page<VA>, paddr: PhysAddr, flags: MemFlags) -> PagingResult<()> {
// Record the number of intermediate tables before allocation to enable rollback on failure.
let intrm_tables_len_before = self.intrm_tables.len();

trace!(
"loongarch64: map_page: vaddr={:#x}, size={:?}, paddr={:#x}, flags={:?}",
page.vaddr.into(),
page.size,
paddr,
flags
);
let entry: &mut PTE = self.get_entry_mut_or_create(page)?;

let entry = self.get_entry_mut_or_create(page)?;
if !entry.is_unused() {
// Rollback before returning error (entry ref goes out of scope here).
let _ = entry;
self.intrm_tables.truncate(intrm_tables_len_before);
return Err(PagingError::AlreadyMapped);
}
trace!("loongarch64: map_page: entry is unused, continue");
Expand All @@ -384,7 +386,7 @@ where
entry.addr(),
entry.flags()
);
Ok(entry)
Ok(())
}

fn unmap_page(&mut self, vaddr: VA) -> PagingResult<(PhysAddr, PageSize)> {
Expand Down Expand Up @@ -491,6 +493,7 @@ where
let _lock = self.clonee_lock.lock();
let mut vaddr = region.start.into();
let mut size = region.size;
let mut mapped_size = 0usize;
while size > 0 {
let paddr = region.mapper.map_fn(vaddr);
let page_size = PageSize::Size4K; // now let's support STLB only
Expand All @@ -502,15 +505,34 @@ where
region.flags
);
let page = Page::new_aligned(vaddr.into(), page_size);
self.inner
.map_page(page, paddr, region.flags)
.map_err(|e: PagingError| {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, e
);
e
})?;
if let Err(map_err) = self.inner.map_page(page, paddr, region.flags) {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, map_err
);
let mut rollback_vaddr = region.start.into();
let mut rollback_size = mapped_size;
while rollback_size > 0 {
let (_, rollback_page_size) =
self.inner.unmap_page(rollback_vaddr.into()).map_err(|rollback_err| {
error!(
"failed to rollback mapped page: {:#x?}, rollback error: {:?}, original map error: {:?}",
rollback_vaddr, rollback_err, map_err
);
rollback_err
})?;
if !rollback_page_size.is_aligned(rollback_vaddr) {
error!("rollback alignment error vaddr={:#x?}", rollback_vaddr);
loop {}
}
assert!(rollback_page_size.is_aligned(rollback_vaddr));
assert!(rollback_page_size as usize <= rollback_size);
rollback_vaddr += rollback_page_size as usize;
rollback_size -= rollback_page_size as usize;
}
return Err(map_err.into());
}
mapped_size += page_size as usize;
vaddr += page_size as usize;
size -= page_size as usize;
}
Expand Down
50 changes: 38 additions & 12 deletions src/arch/riscv64/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,20 @@ where
page: Page<VA>,
paddr: PhysAddr,
mut flags: MemFlags,
) -> PagingResult<&mut PTE> {
let entry: &mut PTE = self.get_entry_mut_or_create(page, &mut flags)?;
) -> PagingResult<()> {
// Record the number of intermediate tables before allocation to enable rollback on failure.
let intrm_tables_len_before = self.intrm_tables.len();

let entry = self.get_entry_mut_or_create(page, &mut flags)?;
if !entry.is_unused() {
// Rollback before returning error (entry ref goes out of scope here).
let _ = entry;
self.intrm_tables.truncate(intrm_tables_len_before);
return Err(PagingError::AlreadyMapped);
}
entry.set_addr(page.size.align_down(paddr));
entry.set_flags(flags);
Ok(entry)
Ok(())
}

fn unmap_page(&mut self, vaddr: VA) -> PagingResult<(PhysAddr, PageSize)> {
Expand Down Expand Up @@ -501,6 +507,7 @@ where
let _lock = self.clonee_lock.lock();
let mut vaddr = region.start.into();
let mut size = region.size;
let mut mapped_size = 0usize;
while size > 0 {
// Hvisor don't support huge page which > 1G.
let paddr = region.mapper.map_fn(vaddr);
Expand All @@ -523,15 +530,34 @@ where
};
// debug!("page_size: {:#x?}", page_size);
let page = Page::new_aligned(vaddr.into(), page_size);
self.inner
.map_page(page, paddr, region.flags)
.map_err(|e: PagingError| {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, e
);
e
})?;
if let Err(map_err) = self.inner.map_page(page, paddr, region.flags) {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, map_err
);
let mut rollback_vaddr = region.start.into();
let mut rollback_size = mapped_size;
while rollback_size > 0 {
let (_, rollback_page_size) =
self.inner.unmap_page(rollback_vaddr.into()).map_err(|rollback_err| {
error!(
"failed to rollback mapped page: {:#x?}, rollback error: {:?}, original map error: {:?}",
rollback_vaddr, rollback_err, map_err
);
rollback_err
})?;
if !rollback_page_size.is_aligned(rollback_vaddr) {
error!("rollback alignment error vaddr={:#x?}", rollback_vaddr);
loop {}
}
assert!(rollback_page_size.is_aligned(rollback_vaddr));
assert!(rollback_page_size as usize <= rollback_size);
rollback_vaddr += rollback_page_size as usize;
rollback_size -= rollback_page_size as usize;
}
return Err(map_err.into());
}
mapped_size += page_size as usize;
vaddr += page_size as usize;
size -= page_size as usize;
}
Expand Down
53 changes: 37 additions & 16 deletions src/arch/x86_64/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,19 +324,20 @@ where
Ok(p1e)
}

fn map_page(
&mut self,
page: Page<VA>,
paddr: PhysAddr,
flags: MemFlags,
) -> PagingResult<&mut PTE> {
fn map_page(&mut self, page: Page<VA>, paddr: PhysAddr, flags: MemFlags) -> PagingResult<()> {
// Record the number of intermediate tables before allocation to enable rollback on failure.
let intrm_tables_len_before = self.intrm_tables.len();

let entry = self.get_entry_mut_or_create(page)?;
if !entry.is_unused() {
// Rollback before returning error (entry ref goes out of scope here).
let _ = entry;
self.intrm_tables.truncate(intrm_tables_len_before);
return Err(PagingError::AlreadyMapped);
}
entry.set_addr(page.size.align_down(paddr));
entry.set_flags(flags, page.size.is_huge());
Ok(entry)
Ok(())
}

fn unmap_page(&mut self, vaddr: VA) -> PagingResult<(PhysAddr, PageSize)> {
Expand Down Expand Up @@ -442,6 +443,7 @@ where
let _lock = self.clonee_lock.lock();
let mut vaddr = region.start.into();
let mut size = region.size;
let mut mapped_size = 0usize;
while size > 0 {
let paddr = region.mapper.map_fn(vaddr);
let page_size = if PageSize::Size1G.is_aligned(vaddr)
Expand All @@ -460,15 +462,34 @@ where
PageSize::Size4K
};
let page = Page::new_aligned(vaddr.into(), page_size);
self.inner
.map_page(page, paddr, region.flags)
.map_err(|e: PagingError| {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, e
);
e
})?;
if let Err(map_err) = self.inner.map_page(page, paddr, region.flags) {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, map_err
);
let mut rollback_vaddr = region.start.into();
let mut rollback_size = mapped_size;
while rollback_size > 0 {
let (_, rollback_page_size) =
self.inner.unmap_page(rollback_vaddr.into()).map_err(|rollback_err| {
error!(
"failed to rollback mapped page: {:#x?}, rollback error: {:?}, original map error: {:?}",
rollback_vaddr, rollback_err, map_err
);
rollback_err
})?;
if !rollback_page_size.is_aligned(rollback_vaddr) {
error!("rollback alignment error vaddr={:#x?}", rollback_vaddr);
loop {}
}
assert!(rollback_page_size.is_aligned(rollback_vaddr));
assert!(rollback_page_size as usize <= rollback_size);
rollback_vaddr += rollback_page_size as usize;
rollback_size -= rollback_page_size as usize;
}
return Err(map_err.into());
}
mapped_size += page_size as usize;
vaddr += page_size as usize;
size -= page_size as usize;
}
Expand Down
Loading
Loading