mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
multiple corrections to page table setup and fix vcpu structs
This commit is contained in:
parent
4b4f22ffcd
commit
b79c31e613
@ -1,9 +1,9 @@
|
|||||||
use crate::sys::{
|
use crate::sys::{
|
||||||
ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext, GetDomainInfo,
|
AddressSize, ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext,
|
||||||
HypercallInit, MaxMem, MaxVcpus, VcpuGuestContext, VcpuGuestContextAny, HYPERVISOR_DOMCTL,
|
GetDomainInfo, HypercallInit, MaxMem, MaxVcpus, VcpuGuestContext, VcpuGuestContextAny,
|
||||||
XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN, XEN_DOMCTL_GETDOMAININFO,
|
HYPERVISOR_DOMCTL, XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN, XEN_DOMCTL_GETDOMAININFO,
|
||||||
XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_INTERFACE_VERSION, XEN_DOMCTL_MAX_MEM,
|
XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_INTERFACE_VERSION, XEN_DOMCTL_MAX_MEM,
|
||||||
XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_SETVCPUCONTEXT,
|
XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_SETVCPUCONTEXT, XEN_DOMCTL_SET_ADDRESS_SIZE,
|
||||||
};
|
};
|
||||||
use crate::{XenCall, XenCallError};
|
use crate::{XenCall, XenCallError};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
@ -117,6 +117,26 @@ impl DomainControl<'_> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_address_size(&self, domid: u32, size: u32) -> Result<(), XenCallError> {
|
||||||
|
trace!(
|
||||||
|
"domctl fd={} set_address_size domid={} size={}",
|
||||||
|
self.call.handle.as_raw_fd(),
|
||||||
|
domid,
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
let mut domctl = DomCtl {
|
||||||
|
cmd: XEN_DOMCTL_SET_ADDRESS_SIZE,
|
||||||
|
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||||
|
domid,
|
||||||
|
value: DomCtlValue {
|
||||||
|
address_size: AddressSize { size },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.call
|
||||||
|
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_vcpu_context(
|
pub fn set_vcpu_context(
|
||||||
&self,
|
&self,
|
||||||
domid: u32,
|
domid: u32,
|
||||||
@ -152,7 +172,7 @@ impl DomainControl<'_> {
|
|||||||
|
|
||||||
pub fn hypercall_init(&self, domid: u32, gmfn: u64) -> Result<(), XenCallError> {
|
pub fn hypercall_init(&self, domid: u32, gmfn: u64) -> Result<(), XenCallError> {
|
||||||
trace!(
|
trace!(
|
||||||
"domctl fd={} hypercall_init domid={} max_vcpus={}",
|
"domctl fd={} hypercall_init domid={} gmfn={}",
|
||||||
self.call.handle.as_raw_fd(),
|
self.call.handle.as_raw_fd(),
|
||||||
domid,
|
domid,
|
||||||
gmfn
|
gmfn
|
||||||
|
@ -207,6 +207,12 @@ pub struct DomCtlVcpuContext {
|
|||||||
pub ctx: u64,
|
pub ctx: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct AddressSize {
|
||||||
|
pub size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub union DomCtlValue {
|
pub union DomCtlValue {
|
||||||
@ -215,8 +221,9 @@ pub union DomCtlValue {
|
|||||||
pub max_mem: MaxMem,
|
pub max_mem: MaxMem,
|
||||||
pub max_cpus: MaxVcpus,
|
pub max_cpus: MaxVcpus,
|
||||||
pub hypercall_init: HypercallInit,
|
pub hypercall_init: HypercallInit,
|
||||||
pub pad: [u8; 128],
|
|
||||||
pub vcpu_context: DomCtlVcpuContext,
|
pub vcpu_context: DomCtlVcpuContext,
|
||||||
|
pub address_size: AddressSize,
|
||||||
|
pub pad: [u8; 128],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -400,7 +407,7 @@ pub struct TrapInfo {
|
|||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct VcpuGuestContext {
|
pub struct VcpuGuestContext {
|
||||||
pub fpu_ctx: VcpuGuestContextFpuCtx,
|
pub fpu_ctx: VcpuGuestContextFpuCtx,
|
||||||
pub flags: c_ulong,
|
pub flags: u64,
|
||||||
pub user_regs: CpuUserRegs,
|
pub user_regs: CpuUserRegs,
|
||||||
pub trap_ctx: [TrapInfo; 256],
|
pub trap_ctx: [TrapInfo; 256],
|
||||||
pub ldt_base: u64,
|
pub ldt_base: u64,
|
||||||
@ -411,6 +418,8 @@ pub struct VcpuGuestContext {
|
|||||||
pub kernel_sp: u64,
|
pub kernel_sp: u64,
|
||||||
pub ctrlreg: [u64; 8],
|
pub ctrlreg: [u64; 8],
|
||||||
pub debugreg: [u64; 8],
|
pub debugreg: [u64; 8],
|
||||||
|
pub event_callback_eip: u64,
|
||||||
|
pub failsafe_callback_eip: u64,
|
||||||
pub syscall_callback_eip: u64,
|
pub syscall_callback_eip: u64,
|
||||||
pub vm_assist: u64,
|
pub vm_assist: u64,
|
||||||
pub fs_base: u64,
|
pub fs_base: u64,
|
||||||
@ -433,6 +442,8 @@ impl Default for VcpuGuestContext {
|
|||||||
kernel_sp: 0,
|
kernel_sp: 0,
|
||||||
ctrlreg: [0; 8],
|
ctrlreg: [0; 8],
|
||||||
debugreg: [0; 8],
|
debugreg: [0; 8],
|
||||||
|
event_callback_eip: 0,
|
||||||
|
failsafe_callback_eip: 0,
|
||||||
syscall_callback_eip: 0,
|
syscall_callback_eip: 0,
|
||||||
vm_assist: 0,
|
vm_assist: 0,
|
||||||
fs_base: 0,
|
fs_base: 0,
|
||||||
|
@ -95,6 +95,8 @@ impl BootSetup<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_memory(&mut self, memkb: u64) -> Result<(), XenClientError> {
|
fn initialize_memory(&mut self, memkb: u64) -> Result<(), XenClientError> {
|
||||||
|
self.domctl.set_address_size(self.domid, 64)?;
|
||||||
|
|
||||||
let mem_mb: u64 = memkb / 1024;
|
let mem_mb: u64 = memkb / 1024;
|
||||||
let page_count: u64 = mem_mb << (20 - XEN_PAGE_SHIFT);
|
let page_count: u64 = mem_mb << (20 - XEN_PAGE_SHIFT);
|
||||||
let mut vmemranges: Vec<VmemRange> = Vec::new();
|
let mut vmemranges: Vec<VmemRange> = Vec::new();
|
||||||
@ -224,8 +226,11 @@ impl BootSetup<'_> {
|
|||||||
let start_info_segment = self.alloc_page()?;
|
let start_info_segment = self.alloc_page()?;
|
||||||
let xenstore_segment = self.alloc_page()?;
|
let xenstore_segment = self.alloc_page()?;
|
||||||
let console_segment = self.alloc_page()?;
|
let console_segment = self.alloc_page()?;
|
||||||
let boot_stack_segment = self.alloc_page()?;
|
|
||||||
let (page_table_segment, page_table) = self.alloc_page_tables(&image_info)?;
|
let (page_table_segment, page_table) = self.alloc_page_tables(&image_info)?;
|
||||||
|
let boot_stack_segment = self.alloc_page()?;
|
||||||
|
if self.virt_pgtab_end > 0 {
|
||||||
|
self.alloc_padding_pages(self.virt_pgtab_end)?;
|
||||||
|
}
|
||||||
Ok(BootState {
|
Ok(BootState {
|
||||||
kernel_segment,
|
kernel_segment,
|
||||||
start_info_segment,
|
start_info_segment,
|
||||||
@ -264,7 +269,7 @@ impl BootSetup<'_> {
|
|||||||
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;
|
let _vcpu = vcpu;
|
||||||
self.domctl.set_vcpu_context(self.domid, 0, None)?;
|
self.domctl.set_vcpu_context(self.domid, 0, Some(&vcpu))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +301,11 @@ impl BootSetup<'_> {
|
|||||||
let p_e = (min(to, lvl.to) - from)
|
let p_e = (min(to, lvl.to) - from)
|
||||||
>> (X86_PAGE_SHIFT + lvl_idx as u64 * X86_PGTABLE_LEVEL_SHIFT);
|
>> (X86_PAGE_SHIFT + lvl_idx as u64 * X86_PGTABLE_LEVEL_SHIFT);
|
||||||
let mut pfn = (max(from, lvl.from) - from)
|
let mut pfn = (max(from, lvl.from) - from)
|
||||||
>> ((X86_PAGE_SHIFT + lvl_idx as u64 * X86_PGTABLE_LEVEL_SHIFT) + lvl.pfn);
|
.checked_shr(
|
||||||
|
((X86_PAGE_SHIFT + lvl_idx as u64 * X86_PGTABLE_LEVEL_SHIFT) + lvl.pfn)
|
||||||
|
as u32,
|
||||||
|
)
|
||||||
|
.unwrap_or(0u64);
|
||||||
|
|
||||||
for p in p_s..p_e + 1 {
|
for p in p_s..p_e + 1 {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -343,7 +352,10 @@ impl BootSetup<'_> {
|
|||||||
image_loader: &dyn BootImageLoader,
|
image_loader: &dyn BootImageLoader,
|
||||||
image_info: &BootImageInfo,
|
image_info: &BootImageInfo,
|
||||||
) -> Result<DomainSegment, XenClientError> {
|
) -> Result<DomainSegment, XenClientError> {
|
||||||
let kernel_segment = self.alloc_segment(image_info.virt_kend - image_info.virt_kstart)?;
|
let kernel_segment = self.alloc_segment(
|
||||||
|
image_info.virt_kstart,
|
||||||
|
image_info.virt_kend - image_info.virt_kstart,
|
||||||
|
)?;
|
||||||
let kernel_segment_ptr = kernel_segment.addr as *mut u8;
|
let kernel_segment_ptr = kernel_segment.addr as *mut u8;
|
||||||
debug!(
|
debug!(
|
||||||
"BootSetup initialize kernel_segment ptr={:#x}",
|
"BootSetup initialize kernel_segment ptr={:#x}",
|
||||||
@ -440,7 +452,7 @@ impl BootSetup<'_> {
|
|||||||
|
|
||||||
let mut try_virt_end: u64;
|
let mut try_virt_end: u64;
|
||||||
loop {
|
loop {
|
||||||
try_virt_end = (self.virt_alloc_end + pages * X86_PAGE_SIZE) | (1 << 22);
|
try_virt_end = (self.virt_alloc_end + pages * X86_PAGE_SIZE) | ((1 << 22) - 1);
|
||||||
self.count_page_tables(&mut table, image_info.virt_base, try_virt_end, 0)?;
|
self.count_page_tables(&mut table, image_info.virt_base, try_virt_end, 0)?;
|
||||||
pages = table.mappings[0].area.pgtables as u64 + extra_pages;
|
pages = table.mappings[0].area.pgtables as u64 + extra_pages;
|
||||||
if self.virt_alloc_end + pages * X86_PAGE_SIZE <= try_virt_end + 1 {
|
if self.virt_alloc_end + pages * X86_PAGE_SIZE <= try_virt_end + 1 {
|
||||||
@ -454,7 +466,7 @@ 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(map.area.pgtables as u64 * X86_PAGE_SIZE)?;
|
segment = self.alloc_segment(0, map.area.pgtables as u64 * X86_PAGE_SIZE)?;
|
||||||
}
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"BootSetup alloc_page_tables table={:?} segment={:?}",
|
"BootSetup alloc_page_tables table={:?} segment={:?}",
|
||||||
@ -463,10 +475,15 @@ impl BootSetup<'_> {
|
|||||||
Ok((segment, table))
|
Ok((segment, table))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_segment(&mut self, size: u64) -> Result<DomainSegment, XenClientError> {
|
fn alloc_segment(&mut self, start: u64, size: u64) -> Result<DomainSegment, XenClientError> {
|
||||||
|
if start > 0 {
|
||||||
|
self.alloc_padding_pages(start)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = self.virt_alloc_end;
|
||||||
let page_size = 1u64 << XEN_PAGE_SHIFT;
|
let page_size = 1u64 << XEN_PAGE_SHIFT;
|
||||||
let pages = (size + page_size - 1) / page_size;
|
let pages = (size + page_size - 1) / page_size;
|
||||||
let start = self.virt_alloc_end;
|
|
||||||
let mut segment = DomainSegment {
|
let mut segment = DomainSegment {
|
||||||
vstart: start,
|
vstart: start,
|
||||||
_vend: 0,
|
_vend: 0,
|
||||||
@ -475,20 +492,58 @@ impl BootSetup<'_> {
|
|||||||
size,
|
size,
|
||||||
_pages: pages,
|
_pages: pages,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.chk_alloc_pages(pages)?;
|
||||||
|
|
||||||
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 {
|
unsafe {
|
||||||
memset(ptr as *mut c_void, 0, (pages * page_size) as usize);
|
memset(ptr as *mut c_void, 0, (pages * page_size) as usize);
|
||||||
}
|
}
|
||||||
self.virt_alloc_end += pages * page_size;
|
|
||||||
segment._vend = self.virt_alloc_end;
|
segment._vend = self.virt_alloc_end;
|
||||||
self.pfn_alloc_end += 1;
|
debug!(
|
||||||
debug!("BootSetup alloc_segment size={} ptr={:#x}", size, ptr);
|
"BootSetup alloc_segment start={:#x} size={} ptr={:#x}",
|
||||||
|
start, size, ptr
|
||||||
|
);
|
||||||
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 page_size = 1u64 << XEN_PAGE_SHIFT;
|
||||||
self.alloc_segment(page_size)
|
self.alloc_segment(0, page_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_padding_pages(&mut self, boundary: u64) -> Result<(), XenClientError> {
|
||||||
|
if (boundary & (X86_PAGE_SIZE - 1)) != 0 {
|
||||||
|
return Err(XenClientError::new(
|
||||||
|
format!("segment boundary isn't page aligned: {:#x}", boundary).as_str(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if boundary < self.virt_alloc_end {
|
||||||
|
return Err(XenClientError::new("segment boundary too low"));
|
||||||
|
}
|
||||||
|
let pages = (boundary - self.virt_alloc_end) / X86_PAGE_SIZE;
|
||||||
|
self.chk_alloc_pages(pages)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chk_alloc_pages(&mut self, pages: u64) -> Result<(), XenClientError> {
|
||||||
|
if pages > self.total_pages
|
||||||
|
|| self.pfn_alloc_end > self.total_pages
|
||||||
|
|| pages > self.total_pages - self.pfn_alloc_end
|
||||||
|
{
|
||||||
|
return Err(XenClientError::new(
|
||||||
|
format!(
|
||||||
|
"segment too large: pages={} total_pages={} pfn_alloc_end={}",
|
||||||
|
pages, self.total_pages, self.pfn_alloc_end
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pfn_alloc_end += pages;
|
||||||
|
self.virt_alloc_end += pages * X86_PAGE_SIZE;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::sys::XEN_PAGE_SHIFT;
|
use crate::sys::XEN_PAGE_SHIFT;
|
||||||
use crate::XenClientError;
|
use crate::XenClientError;
|
||||||
|
|
||||||
|
use crate::x86::X86_PAGE_SHIFT;
|
||||||
use xencall::sys::MmapEntry;
|
use xencall::sys::MmapEntry;
|
||||||
use xencall::XenCall;
|
use xencall::XenCall;
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ impl PhysicalPages<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(page.ptr + ((pfn - page.pfn) << XEN_PAGE_SHIFT));
|
return Ok(page.ptr + ((pfn - page.pfn) << X86_PAGE_SHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
|
@ -3,7 +3,7 @@ use libc::c_char;
|
|||||||
pub const X86_PAGE_SHIFT: u64 = 12;
|
pub const X86_PAGE_SHIFT: u64 = 12;
|
||||||
pub const X86_PAGE_SIZE: u64 = 1 << X86_PAGE_SHIFT;
|
pub const X86_PAGE_SIZE: u64 = 1 << X86_PAGE_SHIFT;
|
||||||
pub const X86_VIRT_BITS: u64 = 48;
|
pub const X86_VIRT_BITS: u64 = 48;
|
||||||
pub const X86_VIRT_MASK: u64 = 1 << X86_VIRT_BITS;
|
pub const X86_VIRT_MASK: u64 = (1 << X86_VIRT_BITS) - 1;
|
||||||
pub const X86_PGTABLE_LEVELS: u64 = 4;
|
pub const X86_PGTABLE_LEVELS: u64 = 4;
|
||||||
pub const X86_PGTABLE_LEVEL_SHIFT: u64 = 9;
|
pub const X86_PGTABLE_LEVEL_SHIFT: u64 = 9;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user