fix multiple oversights that make values not align with original library

This commit is contained in:
Alex Zenla 2024-01-12 02:12:29 -08:00
parent b79c31e613
commit 1f30f8315a
No known key found for this signature in database
GPG Key ID: 067B238899B51269
2 changed files with 38 additions and 14 deletions

View File

@ -1,6 +1,7 @@
use crate::mem::PhysicalPages; use crate::mem::PhysicalPages;
use crate::sys::{ use crate::sys::{
SUPERPAGE_2MB_NR_PFNS, SUPERPAGE_2MB_SHIFT, SUPERPAGE_BATCH_SIZE, XEN_PAGE_SHIFT, SUPERPAGE_2MB_NR_PFNS, SUPERPAGE_2MB_SHIFT, SUPERPAGE_BATCH_SIZE, VGCF_IN_KERNEL, VGCF_ONLINE,
XEN_PAGE_SHIFT,
}; };
use crate::x86::{ use crate::x86::{
PageTable, PageTableMapping, StartInfo, MAX_GUEST_CMDLINE, X86_GUEST_MAGIC, X86_PAGE_SHIFT, PageTable, PageTableMapping, StartInfo, MAX_GUEST_CMDLINE, X86_GUEST_MAGIC, X86_PAGE_SHIFT,
@ -64,6 +65,7 @@ struct VmemRange {
_nid: u32, _nid: u32,
} }
#[derive(Debug)]
pub struct BootState { pub struct BootState {
pub kernel_segment: DomainSegment, pub kernel_segment: DomainSegment,
pub start_info_segment: DomainSegment, pub start_info_segment: DomainSegment,
@ -231,7 +233,7 @@ impl BootSetup<'_> {
if self.virt_pgtab_end > 0 { if self.virt_pgtab_end > 0 {
self.alloc_padding_pages(self.virt_pgtab_end)?; self.alloc_padding_pages(self.virt_pgtab_end)?;
} }
Ok(BootState { let state = BootState {
kernel_segment, kernel_segment,
start_info_segment, start_info_segment,
xenstore_segment, xenstore_segment,
@ -240,12 +242,14 @@ impl BootSetup<'_> {
page_table_segment, page_table_segment,
page_table, page_table,
image_info, image_info,
}) };
debug!("initialize state={:?}", state);
Ok(state)
} }
pub fn boot(&mut self, state: &mut BootState, cmdline: &str) -> Result<(), XenClientError> { pub fn boot(&mut self, state: &mut BootState, cmdline: &str) -> Result<(), XenClientError> {
self.setup_page_tables(state)?; self.setup_page_tables(state)?;
self.setup_start_info(state, cmdline); self.setup_start_info(state, cmdline)?;
self.setup_hypercall_page(&state.image_info)?; self.setup_hypercall_page(&state.image_info)?;
let mut vcpu = VcpuGuestContext::default(); let mut vcpu = VcpuGuestContext::default();
@ -257,7 +261,7 @@ impl BootSetup<'_> {
vcpu.user_regs.rflags = 1 << 9; vcpu.user_regs.rflags = 1 << 9;
vcpu.debugreg[6] = 0xffff0ff0; vcpu.debugreg[6] = 0xffff0ff0;
vcpu.debugreg[7] = 0x00000400; vcpu.debugreg[7] = 0x00000400;
vcpu.flags = (1 << 2) | (1 << 5); 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];
vcpu.ctrlreg[3] = cr3_pfn << 12; vcpu.ctrlreg[3] = cr3_pfn << 12;
vcpu.user_regs.ds = 0xe021; vcpu.user_regs.ds = 0xe021;
@ -268,7 +272,6 @@ impl BootSetup<'_> {
vcpu.user_regs.cs = 0xe019; vcpu.user_regs.cs = 0xe019;
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;
let _vcpu = vcpu;
self.domctl.set_vcpu_context(self.domid, 0, Some(&vcpu))?; self.domctl.set_vcpu_context(self.domid, 0, Some(&vcpu))?;
Ok(()) Ok(())
} }
@ -319,8 +322,8 @@ impl BootSetup<'_> {
Ok(()) Ok(())
} }
fn setup_start_info(&mut self, state: &BootState, cmdline: &str) { fn setup_start_info(&mut self, state: &BootState, cmdline: &str) -> Result<(), XenClientError> {
let info = state.start_info_segment.addr as *mut StartInfo; let info = self.phys.pfn_to_ptr(state.start_info_segment.pfn, 1)? as *mut StartInfo;
unsafe { unsafe {
for (i, c) in X86_GUEST_MAGIC.chars().enumerate() { for (i, c) in X86_GUEST_MAGIC.chars().enumerate() {
(*info).magic[i] = c as c_char; (*info).magic[i] = c as c_char;
@ -345,6 +348,7 @@ impl BootSetup<'_> {
} }
debug!("BootSetup setup_start_info={:?}", *info); debug!("BootSetup setup_start_info={:?}", *info);
} }
Ok(())
} }
fn load_kernel_segment( fn load_kernel_segment(
@ -422,6 +426,7 @@ impl BootSetup<'_> {
if lvl.from >= cmp_lvl.from && lvl.to <= cmp_lvl.to { if lvl.from >= cmp_lvl.from && lvl.to <= cmp_lvl.to {
lvl.from = 0; lvl.from = 0;
lvl.to = 0; lvl.to = 0;
break;
} }
if lvl.from >= cmp_lvl.from && lvl.from <= cmp_lvl.to { if lvl.from >= cmp_lvl.from && lvl.from <= cmp_lvl.to {
@ -437,6 +442,10 @@ impl BootSetup<'_> {
lvl.pgtables = (((lvl.to - lvl.from) >> bits) + 1) as usize; lvl.pgtables = (((lvl.to - lvl.from) >> bits) + 1) as usize;
} }
debug!(
"count_pgtables {:#x}/{}: {:#x} -> {:#x}, {} tables",
mask, bits, lvl.from, lvl.to, lvl.pgtables
);
map.area.pgtables += lvl.pgtables; map.area.pgtables += lvl.pgtables;
} }
Ok(()) Ok(())
@ -447,7 +456,8 @@ impl BootSetup<'_> {
image_info: &BootImageInfo, image_info: &BootImageInfo,
) -> Result<(DomainSegment, PageTable), XenClientError> { ) -> Result<(DomainSegment, PageTable), XenClientError> {
let mut table = PageTable::default(); let mut table = PageTable::default();
let extra_pages = ((512 * 1024) / X86_PAGE_SIZE) + 1; let mut extra_pages = 1;
extra_pages += (512 * 1024) / X86_PAGE_SIZE;
let mut pages = extra_pages; let mut pages = extra_pages;
let mut try_virt_end: u64; let mut try_virt_end: u64;
@ -466,7 +476,8 @@ impl BootSetup<'_> {
map.area.pfn = 0; map.area.pfn = 0;
table.mappings_count += 1; table.mappings_count += 1;
self.virt_pgtab_end = try_virt_end + 1; self.virt_pgtab_end = try_virt_end + 1;
segment = self.alloc_segment(0, map.area.pgtables as u64 * X86_PAGE_SIZE)?; segment =
self.alloc_segment(0, (map.area.pgtables as u64 * X86_PAGE_SIZE) + extra_pages)?;
} }
debug!( debug!(
"BootSetup alloc_page_tables table={:?} segment={:?}", "BootSetup alloc_page_tables table={:?} segment={:?}",
@ -502,15 +513,26 @@ impl BootSetup<'_> {
} }
segment._vend = self.virt_alloc_end; segment._vend = self.virt_alloc_end;
debug!( debug!(
"BootSetup alloc_segment start={:#x} size={} ptr={:#x}", "alloc_segment {:#x} -> {:#x} (pfn {:#x} + {:#x} pages)",
start, size, ptr start, segment._vend, segment.pfn, pages
); );
Ok(segment) Ok(segment)
} }
fn alloc_page(&mut self) -> Result<DomainSegment, XenClientError> { fn alloc_page(&mut self) -> Result<DomainSegment, XenClientError> {
let page_size = 1u64 << XEN_PAGE_SHIFT; let start = self.virt_alloc_end;
self.alloc_segment(0, page_size) let pfn = self.pfn_alloc_end;
self.chk_alloc_pages(1)?;
debug!("alloc_page {:#x} (pfn {:#x})", start, pfn);
Ok(DomainSegment {
vstart: start,
_vend: (start + X86_PAGE_SIZE) - 1,
pfn,
addr: 0,
size: 0,
_pages: 1,
})
} }
fn alloc_padding_pages(&mut self, boundary: u64) -> Result<(), XenClientError> { fn alloc_padding_pages(&mut self, boundary: u64) -> Result<(), XenClientError> {

View File

@ -119,3 +119,5 @@ pub const XEN_PAGE_MASK: u64 = !(XEN_PAGE_SIZE - 1);
pub const SUPERPAGE_BATCH_SIZE: u64 = 512; pub const SUPERPAGE_BATCH_SIZE: u64 = 512;
pub const SUPERPAGE_2MB_SHIFT: u64 = 9; pub const SUPERPAGE_2MB_SHIFT: u64 = 9;
pub const SUPERPAGE_2MB_NR_PFNS: u64 = 1u64 << SUPERPAGE_2MB_SHIFT; pub const SUPERPAGE_2MB_NR_PFNS: u64 = 1u64 << SUPERPAGE_2MB_SHIFT;
pub const VGCF_IN_KERNEL: u64 = 1 << 2;
pub const VGCF_ONLINE: u64 = 1 << 5;