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,
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,
},
},
};

View File

@ -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)
}
}

View File

@ -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(())
}

View File

@ -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)",