From c9f39699dcc9bd48053493f99182d49579ea9286 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Sun, 14 Jan 2024 16:00:44 -0800 Subject: [PATCH] multiple fixes and cleanup --- xencall/src/domctl.rs | 13 +++--- xencall/src/memory.rs | 9 ++-- xenclient/examples/boot.rs | 2 +- xenclient/src/boot.rs | 85 ++++++++++++++++++++++++++++++-------- 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/xencall/src/domctl.rs b/xencall/src/domctl.rs index f24e622..334c2bd 100644 --- a/xencall/src/domctl.rs +++ b/xencall/src/domctl.rs @@ -188,7 +188,7 @@ impl DomainControl<'_> { &self, domid: u32, vcpu: u32, - context: Option<&VcpuGuestContext>, + context: &VcpuGuestContext, ) -> Result<(), XenCallError> { trace!( "domctl fd={} set_vcpu_context domid={} context={:?}", @@ -196,7 +196,10 @@ impl DomainControl<'_> { domid, context, ); - let mut wrapper = context.map(|ctx| VcpuGuestContextAny { value: *ctx }); + + let mut value = VcpuGuestContextAny { + value: *context, + }; let mut domctl = DomCtl { cmd: XEN_DOMCTL_SETVCPUCONTEXT, interface_version: XEN_DOMCTL_INTERFACE_VERSION, @@ -204,11 +207,7 @@ impl DomainControl<'_> { value: DomCtlValue { vcpu_context: DomCtlVcpuContext { vcpu, - ctx: if wrapper.is_some() { - addr_of_mut!(wrapper) as c_ulong - } else { - 0 - }, + ctx: addr_of_mut!(value) as c_ulong, }, }, }; diff --git a/xencall/src/memory.rs b/xencall/src/memory.rs index 68ba896..6e73604 100644 --- a/xencall/src/memory.rs +++ b/xencall/src/memory.rs @@ -3,7 +3,7 @@ use crate::sys::{ }; use crate::{XenCall, XenCallError}; -use log::{trace}; +use log::trace; use std::ffi::c_ulong; use std::os::fd::AsRawFd; use std::ptr::addr_of_mut; @@ -52,11 +52,14 @@ impl MemoryControl<'_> { self.call.multicall(calls)?; let code = calls[0].result; if code > !0xfff { - return Err(XenCallError::new("failed to populate physmap")); + return Err(XenCallError::new( + format!("failed to populate physmap: {:#x}", code).as_str(), + )); } if code as usize > extent_starts.len() { return Err(XenCallError::new("failed to populate physmap")); } - Ok(extent_starts[0..code as usize].to_vec()) + let extents = extent_starts[0..code as usize].to_vec(); + Ok(extents) } } diff --git a/xenclient/examples/boot.rs b/xenclient/examples/boot.rs index 1548754..f649ecd 100644 --- a/xenclient/examples/boot.rs +++ b/xenclient/examples/boot.rs @@ -38,7 +38,7 @@ fn boot( let image_loader = ElfImageLoader::load_file_kernel(kernel_image_path)?; let memctl = MemoryControl::new(call); let mut boot = BootSetup::new(call, domctl, &memctl, domid); - let mut state = boot.initialize(&image_loader, 512 * 1024)?; + let mut state = boot.initialize(&image_loader, 128 * 1024)?; boot.boot(&mut state, "debug")?; Ok(()) } diff --git a/xenclient/src/boot.rs b/xenclient/src/boot.rs index 3d414fc..36a7c5f 100644 --- a/xenclient/src/boot.rs +++ b/xenclient/src/boot.rs @@ -9,11 +9,10 @@ use crate::x86::{ X86_VIRT_MASK, }; use crate::XenClientError; -use libc::{c_char, memset}; +use libc::c_char; use log::{debug, trace}; use slice_copy::copy; use std::cmp::{max, min}; -use std::ffi::c_void; use std::slice; use xencall::domctl::DomainControl; use xencall::memory::MemoryControl; @@ -59,6 +58,7 @@ pub struct DomainSegment { _pages: u64, } +#[derive(Debug)] struct VmemRange { start: u64, end: u64, @@ -154,12 +154,13 @@ impl BootSetup<'_> { j += 1; } + let extents_init_slice = extents_init.as_slice(); let extents = self.memctl.populate_physmap( self.domid, count, SUPERPAGE_2MB_SHIFT as u32, 0, - extents_init.as_slice(), + &extents_init_slice[0usize..count as usize], )?; pfn = pfn_base_idx; @@ -181,17 +182,20 @@ impl BootSetup<'_> { let allocsz = (1024 * 1024).min(pages - j); let p2m_idx = (pfn_base + j) as usize; let p2m_end_idx = p2m_idx + allocsz as usize; - let result = self.memctl.populate_physmap( - self.domid, - allocsz, - 0, - 0, - &p2m[p2m_idx..p2m_end_idx], - )?; + let input_extent_starts = &p2m[p2m_idx..p2m_end_idx]; + let result = + self.memctl + .populate_physmap(self.domid, allocsz, 0, 0, input_extent_starts)?; if result.len() != allocsz as usize { return Err(XenClientError::new( - format!("failed to populate physmap: {:?}", result).as_str(), + format!( + "failed to populate physmap: wanted={} received={} input_extents={}", + allocsz, + result.len(), + input_extent_starts.len() + ) + .as_str(), )); } copy(p2m.as_mut_slice(), result.as_slice()); @@ -268,6 +272,10 @@ impl BootSetup<'_> { vcpu.debugreg[7] = 0x00000400; vcpu.flags = VGCF_IN_KERNEL | VGCF_ONLINE; let cr3_pfn = self.phys.p2m[state.page_table_segment.pfn as usize]; + debug!( + "cr3: pfn {:#x} mfn {:#x}", + state.page_table_segment.pfn, cr3_pfn + ); vcpu.ctrlreg[3] = cr3_pfn << 12; vcpu.user_regs.ds = 0x0; vcpu.user_regs.es = 0x0; @@ -277,7 +285,7 @@ impl BootSetup<'_> { vcpu.user_regs.cs = 0xe033; vcpu.kernel_ss = vcpu.user_regs.ss as u64; vcpu.kernel_sp = vcpu.user_regs.rsp; - self.domctl.set_vcpu_context(self.domid, 0, Some(&vcpu))?; + self.domctl.set_vcpu_context(self.domid, 0, &vcpu)?; Ok(()) } @@ -323,9 +331,12 @@ impl BootSetup<'_> { ) .unwrap_or(0u64); - for p in p_s..p_e + 1 { + for p in p_s..p_e { + let prot = self.get_pg_prot(lvl_idx, pfn, &state.page_table); + unsafe { - *pg.add(p as usize) = self.phys.p2m[pfn as usize] << X86_PAGE_SHIFT; + *pg.add(p as usize) = + (self.phys.p2m[pfn as usize] << X86_PAGE_SHIFT) | prot; } pfn += 1; } @@ -335,6 +346,46 @@ impl BootSetup<'_> { Ok(()) } + const PAGE_PRESENT: u64 = 0x001; + const PAGE_RW: u64 = 0x002; + const PAGE_ACCESSED: u64 = 0x020; + const PAGE_DIRTY: u64 = 0x040; + const PAGE_USER: u64 = 0x004; + fn get_pg_prot(&mut self, l: usize, pfn: u64, table: &PageTable) -> u64 { + let prot = [ + BootSetup::PAGE_PRESENT | BootSetup::PAGE_RW | BootSetup::PAGE_ACCESSED, + BootSetup::PAGE_PRESENT + | BootSetup::PAGE_RW + | BootSetup::PAGE_ACCESSED + | BootSetup::PAGE_DIRTY + | BootSetup::PAGE_USER, + BootSetup::PAGE_PRESENT + | BootSetup::PAGE_RW + | BootSetup::PAGE_ACCESSED + | BootSetup::PAGE_DIRTY + | BootSetup::PAGE_USER, + BootSetup::PAGE_PRESENT + | BootSetup::PAGE_RW + | BootSetup::PAGE_ACCESSED + | BootSetup::PAGE_DIRTY + | BootSetup::PAGE_USER, + ]; + + let prot = prot[l]; + if l > 0 { + return prot; + } + + for map in &table.mappings { + let pfn_s = map.levels[(X86_PGTABLE_LEVELS - 1) as usize].pfn; + let pfn_e = map.area.pgtables as u64 + pfn_s; + if pfn > pfn_s && pfn < pfn_e { + return prot & !BootSetup::PAGE_RW; + } + } + prot + } + fn setup_start_info(&mut self, state: &BootState, cmdline: &str) -> Result<(), XenClientError> { let info = self.phys.pfn_to_ptr(state.start_info_segment.pfn, 1)? as *mut StartInfo; unsafe { @@ -543,9 +594,9 @@ impl BootSetup<'_> { let ptr = self.phys.pfn_to_ptr(segment.pfn, pages)?; segment.addr = ptr; - unsafe { - memset(ptr as *mut c_void, 0, (pages * page_size) as usize); - } + let slice = + unsafe { slice::from_raw_parts_mut(ptr as *mut u8, (pages * page_size) as usize) }; + slice.fill(0); segment._vend = self.virt_alloc_end; debug!( "BootSetup alloc_segment {:#x} -> {:#x} (pfn {:#x} + {:#x} pages)",