diff --git a/xencall/src/domctl.rs b/xencall/src/domctl.rs index 092051e..cb73d1a 100644 --- a/xencall/src/domctl.rs +++ b/xencall/src/domctl.rs @@ -6,7 +6,7 @@ use crate::sys::{ }; use crate::{XenCall, XenCallError}; use std::ffi::c_ulong; -use std::ptr::addr_of; +use std::ptr::addr_of_mut; pub struct DomainControl<'a> { call: &'a XenCall, @@ -18,7 +18,7 @@ impl DomainControl<'_> { } pub fn get_domain_info(&self, domid: u32) -> Result { - let domctl = DomCtl { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_GETDOMAININFO, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid, @@ -48,24 +48,24 @@ impl DomainControl<'_> { }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(unsafe { domctl.value.get_domain_info }) } pub fn create_domain(&self, create_domain: CreateDomain) -> Result { - let domctl = DomCtl { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_CREATEDOMAIN, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid: 0, value: DomCtlValue { create_domain }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(domctl.domid) } - pub fn set_max_mem(&mut self, domid: u32, memkb: u64) -> Result<(), XenCallError> { - let domctl = DomCtl { + pub fn set_max_mem(&self, domid: u32, memkb: u64) -> Result<(), XenCallError> { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_MAX_MEM, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid, @@ -74,12 +74,12 @@ impl DomainControl<'_> { }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(()) } - pub fn set_max_vcpus(&mut self, domid: u32, max_vcpus: u32) -> Result<(), XenCallError> { - let domctl = DomCtl { + pub fn set_max_vcpus(&self, domid: u32, max_vcpus: u32) -> Result<(), XenCallError> { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_MAX_VCPUS, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid, @@ -88,12 +88,12 @@ impl DomainControl<'_> { }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(()) } pub fn hypercall_init(&self, domid: u32, gmfn: u64) -> Result<(), XenCallError> { - let domctl = DomCtl { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_HYPERCALL_INIT, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid, @@ -102,19 +102,19 @@ impl DomainControl<'_> { }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(()) } pub fn destroy_domain(&self, domid: u32) -> Result<(), XenCallError> { - let domctl = DomCtl { + let mut domctl = DomCtl { cmd: XEN_DOMCTL_DESTROYDOMAIN, interface_version: XEN_DOMCTL_INTERFACE_VERSION, domid, value: DomCtlValue { pad: [0; 128] }, }; self.call - .hypercall1(HYPERVISOR_DOMCTL, addr_of!(domctl) as c_ulong)?; + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; Ok(()) } } diff --git a/xencall/src/lib.rs b/xencall/src/lib.rs index b7bb933..7338362 100644 --- a/xencall/src/lib.rs +++ b/xencall/src/lib.rs @@ -12,7 +12,7 @@ use std::ffi::{c_long, c_ulong, c_void}; use std::fmt::{Display, Formatter}; use std::fs::{File, OpenOptions}; use std::os::fd::AsRawFd; -use std::ptr::addr_of; +use std::ptr::addr_of_mut; pub struct XenCall { pub handle: File, @@ -143,7 +143,7 @@ impl XenCall { pub fn mmap_batch( &self, domid: u32, - count: u64, + num: u64, addr: u64, mfns: Vec, ) -> Result { @@ -151,7 +151,7 @@ impl XenCall { let mut mfns = mfns.clone(); let mut errors = vec![0i32; mfns.len()]; let mut batch = MmapBatch { - num: count as u32, + num: num as u32, domid: domid as u16, addr, mfns: mfns.as_mut_ptr(), @@ -163,13 +163,13 @@ impl XenCall { } pub fn get_version_capabilities(&self) -> Result { - let info = XenCapabilitiesInfo { + let mut info = XenCapabilitiesInfo { capabilities: [0; 1024], }; self.hypercall2( HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, - addr_of!(info) as c_ulong, + addr_of_mut!(info) as c_ulong, )?; Ok(info) } diff --git a/xencall/src/memory.rs b/xencall/src/memory.rs index e41cd35..4b35561 100644 --- a/xencall/src/memory.rs +++ b/xencall/src/memory.rs @@ -3,7 +3,7 @@ use crate::{XenCall, XenCallError}; use std::ffi::c_ulong; -use std::ptr::addr_of; +use std::ptr::addr_of_mut; pub struct MemoryControl<'a> { call: &'a XenCall, @@ -22,19 +22,28 @@ impl MemoryControl<'_> { mem_flags: u32, extent_starts: &[u64], ) -> Result, XenCallError> { - let extent_starts = extent_starts.to_vec(); - let reservation = MemoryReservation { - extent_start: addr_of!(extent_starts) as c_ulong, + let mut extent_starts = extent_starts.to_vec(); + let mut reservation = MemoryReservation { + extent_start: extent_starts.as_mut_ptr() as c_ulong, nr_extents, extent_order, mem_flags, domid: domid as u16, }; - self.call.hypercall2( + let code = self.call.hypercall2( HYPERVISOR_MEMORY_OP, XEN_MEM_POPULATE_PHYSMAP as c_ulong, - addr_of!(reservation) as c_ulong, + addr_of_mut!(reservation) as c_ulong, )?; - Ok(extent_starts) + + if code < 0 { + return Err(XenCallError::new("failed to populate physmap")); + } + + if code as usize > extent_starts.len() { + return Err(XenCallError::new("failed to populate physmap")); + } + + Ok(extent_starts[0..code as usize].to_vec()) } } diff --git a/xenclient/examples/boot.rs b/xenclient/examples/boot.rs index 5f60cb8..4542ce3 100644 --- a/xenclient/examples/boot.rs +++ b/xenclient/examples/boot.rs @@ -23,8 +23,8 @@ fn main() -> Result<(), XenClientError> { let image_info = image_loader.parse()?; println!("loaded kernel image into memory: {:?}", image_info); let memctl = MemoryControl::new(&call); - let mut boot = BootSetup::new(&call, &domctl, &memctl, domid, 512 * 1024); - boot.initialize(image_info)?; + let mut boot = BootSetup::new(&call, &domctl, &memctl, domid); + boot.initialize(image_info, 512 * 1024)?; domctl.destroy_domain(domid)?; println!("domain destroyed: {}", domid); Ok(()) diff --git a/xenclient/src/boot.rs b/xenclient/src/boot.rs index cbe6a50..2428aa3 100644 --- a/xenclient/src/boot.rs +++ b/xenclient/src/boot.rs @@ -30,7 +30,6 @@ pub struct BootSetup<'a> { memctl: &'a MemoryControl<'a>, phys: PhysicalPages<'a>, domid: u32, - memkb: u64, virt_alloc_end: u64, pfn_alloc_end: u64, } @@ -55,23 +54,20 @@ impl BootSetup<'_> { domctl: &'a DomainControl<'a>, memctl: &'a MemoryControl<'a>, domid: u32, - memkb: u64, ) -> BootSetup<'a> { BootSetup { domctl, memctl, phys: PhysicalPages::new(call, domid), domid, - memkb, virt_alloc_end: 0, pfn_alloc_end: 0, } } - fn initialize_memory(&mut self) -> Result<(), XenClientError> { - let mem_mb: u64 = self.memkb / 1024; + fn initialize_memory(&mut self, memkb: u64) -> Result<(), XenClientError> { + let mem_mb: u64 = memkb / 1024; let page_count: u64 = mem_mb << (20 - XEN_PAGE_SHIFT); - let mut pfn_base_idx: u64 = 0; let mut vmemranges: Vec = Vec::new(); let stub = VmemRange { start: 0, @@ -105,15 +101,20 @@ impl BootSetup<'_> { } let mut super_pages = pages >> SUPERPAGE_2MB_SHIFT; + let mut pfn_base_idx: u64 = pfn_base; while super_pages > 0 { let count = super_pages.min(SUPERPAGE_BATCH_SIZE); super_pages -= count; - for (i, pfn) in (pfn_base_idx..(count << SUPERPAGE_2MB_SHIFT)) - .step_by(SUPERPAGE_2MB_NR_PFNS as usize) - .enumerate() - { - extents[i] = p2m[pfn as usize]; + let mut j: usize = 0; + let mut pfn: u64 = pfn_base_idx; + loop { + if pfn >= pfn_base_idx + (count << SUPERPAGE_2MB_SHIFT) { + break; + } + extents[j] = p2m[pfn as usize]; + pfn += SUPERPAGE_2MB_NR_PFNS; + j += 1; } let starts = self.memctl.populate_physmap( @@ -124,31 +125,36 @@ impl BootSetup<'_> { extents.as_slice(), )?; - let pfn = pfn_base; + pfn = pfn_base_idx; for mfn in starts { for k in 0..SUPERPAGE_2MB_NR_PFNS { p2m[pfn as usize] = mfn + k; + pfn += 1; } } pfn_base_idx = pfn; } let mut j = pfn_base_idx - pfn_base; - loop { if j >= pages { break; } - let allocsz = (pages - j).min(1024 * 1024); - let result = self.memctl.populate_physmap( - self.domid, - allocsz, - 0, - 0, - &[p2m[(pfn_base + j) as usize]], - )?; - p2m[(pfn_base + j) as usize] = result[0]; + let allocsz = (1024 * 1024).min(pages - j); + let p2m_idx = (pfn_base + j) as usize; + let extent_start = p2m[p2m_idx]; + let result = + self.memctl + .populate_physmap(self.domid, allocsz, 0, 0, &[extent_start])?; + + if result.len() != allocsz as usize { + return Err(XenClientError::new( + format!("failed to populate physmap: {:?}", result).as_str(), + )); + } + + p2m[p2m_idx] = result[0]; j += allocsz; } } @@ -165,8 +171,13 @@ impl BootSetup<'_> { Ok(()) } - pub fn initialize(&mut self, image_info: BootImageInfo) -> Result<(), XenClientError> { - self.initialize_memory()?; + pub fn initialize( + &mut self, + image_info: BootImageInfo, + memkb: u64, + ) -> Result<(), XenClientError> { + self.domctl.set_max_mem(self.domid, memkb)?; + self.initialize_memory(memkb)?; let _kernel_segment = self.alloc_segment(image_info.virt_kend - image_info.virt_kstart)?; self.initialize_hypercall(image_info)?; Ok(()) diff --git a/xenclient/src/create.rs b/xenclient/src/create.rs index 50347ce..08bdb64 100644 --- a/xenclient/src/create.rs +++ b/xenclient/src/create.rs @@ -41,11 +41,7 @@ impl DomainConfig { self.put_domain("memory/videoram", videokb.to_string()); } - pub fn configure_cpus(&mut self, maxvcpus: u32) { - for i in 0..maxvcpus { - println!("{}", i); - } - } + pub fn configure_cpus(&mut self, _maxvcpus: u32) {} pub fn configure_pv(&mut self, pv: PvDomainConfig) { self.put_vm_str("image/ostype", "linux"); diff --git a/xenclient/src/mem.rs b/xenclient/src/mem.rs index a81e06d..f5ffa8c 100644 --- a/xenclient/src/mem.rs +++ b/xenclient/src/mem.rs @@ -7,7 +7,7 @@ use xencall::XenCall; pub struct PhysicalPage { pfn: u64, ptr: u64, - size: u64, + count: u64, } pub struct PhysicalPages<'a> { @@ -33,7 +33,7 @@ impl PhysicalPages<'_> { pub fn pfn_to_ptr(&mut self, pfn: u64, count: u64) -> Result { for page in &self.pages { - if pfn >= page.pfn + page.size { + if pfn >= page.pfn + page.count { continue; } @@ -42,7 +42,7 @@ impl PhysicalPages<'_> { continue; } - if pfn < page.pfn || (pfn + count) > page.pfn + page.size { + if pfn < page.pfn || (pfn + count) > page.pfn + page.count { return Err(XenClientError::new("request overlaps allocated block")); } } else { @@ -50,7 +50,7 @@ impl PhysicalPages<'_> { continue; } - if pfn >= page.pfn + page.size { + if pfn >= page.pfn + page.count { continue; } } @@ -82,7 +82,7 @@ impl PhysicalPages<'_> { } } - let size = (num as u64) << XEN_PAGE_SHIFT; + let size = count << XEN_PAGE_SHIFT; let addr = self .call .mmap(0, size) @@ -91,7 +91,7 @@ impl PhysicalPages<'_> { let page = PhysicalPage { pfn, ptr: addr, - size, + count, }; self.pages.push(page); Ok(addr)