multiple fixes and cleanup

This commit is contained in:
Alex Zenla 2024-01-14 16:00:44 -08:00
parent a9275c4bdf
commit c9f39699dc
No known key found for this signature in database
GPG Key ID: 067B238899B51269
4 changed files with 81 additions and 28 deletions

View File

@ -188,7 +188,7 @@ impl DomainControl<'_> {
&self, &self,
domid: u32, domid: u32,
vcpu: u32, vcpu: u32,
context: Option<&VcpuGuestContext>, context: &VcpuGuestContext,
) -> Result<(), XenCallError> { ) -> Result<(), XenCallError> {
trace!( trace!(
"domctl fd={} set_vcpu_context domid={} context={:?}", "domctl fd={} set_vcpu_context domid={} context={:?}",
@ -196,7 +196,10 @@ impl DomainControl<'_> {
domid, domid,
context, context,
); );
let mut wrapper = context.map(|ctx| VcpuGuestContextAny { value: *ctx });
let mut value = VcpuGuestContextAny {
value: *context,
};
let mut domctl = DomCtl { let mut domctl = DomCtl {
cmd: XEN_DOMCTL_SETVCPUCONTEXT, cmd: XEN_DOMCTL_SETVCPUCONTEXT,
interface_version: XEN_DOMCTL_INTERFACE_VERSION, interface_version: XEN_DOMCTL_INTERFACE_VERSION,
@ -204,11 +207,7 @@ impl DomainControl<'_> {
value: DomCtlValue { value: DomCtlValue {
vcpu_context: DomCtlVcpuContext { vcpu_context: DomCtlVcpuContext {
vcpu, vcpu,
ctx: if wrapper.is_some() { ctx: addr_of_mut!(value) as c_ulong,
addr_of_mut!(wrapper) as c_ulong
} else {
0
},
}, },
}, },
}; };

View File

@ -3,7 +3,7 @@ use crate::sys::{
}; };
use crate::{XenCall, XenCallError}; use crate::{XenCall, XenCallError};
use log::{trace}; use log::trace;
use std::ffi::c_ulong; use std::ffi::c_ulong;
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::ptr::addr_of_mut; use std::ptr::addr_of_mut;
@ -52,11 +52,14 @@ impl MemoryControl<'_> {
self.call.multicall(calls)?; self.call.multicall(calls)?;
let code = calls[0].result; let code = calls[0].result;
if code > !0xfff { 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() { if code as usize > extent_starts.len() {
return Err(XenCallError::new("failed to populate physmap")); 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)
} }
} }

View File

@ -38,7 +38,7 @@ fn boot(
let image_loader = ElfImageLoader::load_file_kernel(kernel_image_path)?; let image_loader = ElfImageLoader::load_file_kernel(kernel_image_path)?;
let memctl = MemoryControl::new(call); let memctl = MemoryControl::new(call);
let mut boot = BootSetup::new(call, domctl, &memctl, domid); 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")?; boot.boot(&mut state, "debug")?;
Ok(()) Ok(())
} }

View File

@ -9,11 +9,10 @@ use crate::x86::{
X86_VIRT_MASK, X86_VIRT_MASK,
}; };
use crate::XenClientError; use crate::XenClientError;
use libc::{c_char, memset}; use libc::c_char;
use log::{debug, trace}; use log::{debug, trace};
use slice_copy::copy; use slice_copy::copy;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::ffi::c_void;
use std::slice; use std::slice;
use xencall::domctl::DomainControl; use xencall::domctl::DomainControl;
use xencall::memory::MemoryControl; use xencall::memory::MemoryControl;
@ -59,6 +58,7 @@ pub struct DomainSegment {
_pages: u64, _pages: u64,
} }
#[derive(Debug)]
struct VmemRange { struct VmemRange {
start: u64, start: u64,
end: u64, end: u64,
@ -154,12 +154,13 @@ impl BootSetup<'_> {
j += 1; j += 1;
} }
let extents_init_slice = extents_init.as_slice();
let extents = self.memctl.populate_physmap( let extents = self.memctl.populate_physmap(
self.domid, self.domid,
count, count,
SUPERPAGE_2MB_SHIFT as u32, SUPERPAGE_2MB_SHIFT as u32,
0, 0,
extents_init.as_slice(), &extents_init_slice[0usize..count as usize],
)?; )?;
pfn = pfn_base_idx; pfn = pfn_base_idx;
@ -181,17 +182,20 @@ impl BootSetup<'_> {
let allocsz = (1024 * 1024).min(pages - j); let allocsz = (1024 * 1024).min(pages - j);
let p2m_idx = (pfn_base + j) as usize; let p2m_idx = (pfn_base + j) as usize;
let p2m_end_idx = p2m_idx + allocsz as usize; let p2m_end_idx = p2m_idx + allocsz as usize;
let result = self.memctl.populate_physmap( let input_extent_starts = &p2m[p2m_idx..p2m_end_idx];
self.domid, let result =
allocsz, self.memctl
0, .populate_physmap(self.domid, allocsz, 0, 0, input_extent_starts)?;
0,
&p2m[p2m_idx..p2m_end_idx],
)?;
if result.len() != allocsz as usize { if result.len() != allocsz as usize {
return Err(XenClientError::new( 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()); copy(p2m.as_mut_slice(), result.as_slice());
@ -268,6 +272,10 @@ impl BootSetup<'_> {
vcpu.debugreg[7] = 0x00000400; vcpu.debugreg[7] = 0x00000400;
vcpu.flags = VGCF_IN_KERNEL | VGCF_ONLINE; vcpu.flags = VGCF_IN_KERNEL | VGCF_ONLINE;
let cr3_pfn = self.phys.p2m[state.page_table_segment.pfn as usize]; 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.ctrlreg[3] = cr3_pfn << 12;
vcpu.user_regs.ds = 0x0; vcpu.user_regs.ds = 0x0;
vcpu.user_regs.es = 0x0; vcpu.user_regs.es = 0x0;
@ -277,7 +285,7 @@ impl BootSetup<'_> {
vcpu.user_regs.cs = 0xe033; vcpu.user_regs.cs = 0xe033;
vcpu.kernel_ss = vcpu.user_regs.ss as u64; vcpu.kernel_ss = vcpu.user_regs.ss as u64;
vcpu.kernel_sp = vcpu.user_regs.rsp; 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(()) Ok(())
} }
@ -323,9 +331,12 @@ impl BootSetup<'_> {
) )
.unwrap_or(0u64); .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 { 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; pfn += 1;
} }
@ -335,6 +346,46 @@ impl BootSetup<'_> {
Ok(()) 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> { 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; let info = self.phys.pfn_to_ptr(state.start_info_segment.pfn, 1)? as *mut StartInfo;
unsafe { unsafe {
@ -543,9 +594,9 @@ impl BootSetup<'_> {
let ptr = self.phys.pfn_to_ptr(segment.pfn, pages)?; let ptr = self.phys.pfn_to_ptr(segment.pfn, pages)?;
segment.addr = ptr; segment.addr = ptr;
unsafe { let slice =
memset(ptr as *mut c_void, 0, (pages * page_size) as usize); unsafe { slice::from_raw_parts_mut(ptr as *mut u8, (pages * page_size) as usize) };
} slice.fill(0);
segment._vend = self.virt_alloc_end; segment._vend = self.virt_alloc_end;
debug!( debug!(
"BootSetup alloc_segment {:#x} -> {:#x} (pfn {:#x} + {:#x} pages)", "BootSetup alloc_segment {:#x} -> {:#x} (pfn {:#x} + {:#x} pages)",