mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
krata: begin working on arm64 support
This commit is contained in:
parent
a8b5ed1138
commit
f4af71cb2f
@ -262,7 +262,10 @@ impl Default for CreateDomain {
|
||||
CreateDomain {
|
||||
ssidref: SECINITSID_DOMU,
|
||||
handle: Uuid::new_v4().into_bytes(),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
flags: 0,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
flags: 1 << XEN_DOMCTL_CDF_HVM_GUEST,
|
||||
iommu_opts: 0,
|
||||
max_vcpus: 1,
|
||||
max_evtchn_port: 1023,
|
||||
@ -271,10 +274,7 @@ impl Default for CreateDomain {
|
||||
grant_opts: 2,
|
||||
vmtrace_size: 0,
|
||||
cpupool_id: 0,
|
||||
arch_domain_config: ArchDomainConfig {
|
||||
emulation_flags: 0,
|
||||
misc_flags: 0,
|
||||
},
|
||||
arch_domain_config: ArchDomainConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,11 +311,23 @@ pub struct GetPageFrameInfo3 {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub struct ArchDomainConfig {
|
||||
pub emulation_flags: u32,
|
||||
pub misc_flags: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub struct ArchDomainConfig {
|
||||
pub gic_version: u8,
|
||||
pub sve_v1: u8,
|
||||
pub tee_type: u8,
|
||||
pub nr_spis: u8,
|
||||
pub clock_frequency: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct MaxMem {
|
||||
@ -390,6 +402,7 @@ impl Default for VcpuGuestContextFpuCtx {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub struct CpuUserRegs {
|
||||
pub r15: u64,
|
||||
pub r14: u64,
|
||||
@ -429,6 +442,7 @@ pub struct CpuUserRegs {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub struct TrapInfo {
|
||||
pub vector: u8,
|
||||
pub flags: u8,
|
||||
@ -438,6 +452,7 @@ pub struct TrapInfo {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub struct VcpuGuestContext {
|
||||
pub fpu_ctx: VcpuGuestContextFpuCtx,
|
||||
pub flags: u64,
|
||||
@ -460,6 +475,7 @@ pub struct VcpuGuestContext {
|
||||
pub gs_base_user: u64,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl Default for VcpuGuestContext {
|
||||
fn default() -> Self {
|
||||
VcpuGuestContext {
|
||||
@ -486,6 +502,65 @@ impl Default for VcpuGuestContext {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub struct CpuUserRegs {
|
||||
pub x0: u64,
|
||||
pub x1: u64,
|
||||
pub x2: u64,
|
||||
pub x3: u64,
|
||||
pub x4: u64,
|
||||
pub x5: u64,
|
||||
pub x6: u64,
|
||||
pub x7: u64,
|
||||
pub x8: u64,
|
||||
pub x9: u64,
|
||||
pub x10: u64,
|
||||
pub x11: u64,
|
||||
pub x12: u64,
|
||||
pub x13: u64,
|
||||
pub x14: u64,
|
||||
pub x15: u64,
|
||||
pub x16: u64,
|
||||
pub x17: u64,
|
||||
pub x18: u64,
|
||||
pub x19: u64,
|
||||
pub x20: u64,
|
||||
pub x21: u64,
|
||||
pub x22: u64,
|
||||
pub x23: u64,
|
||||
pub x24: u64,
|
||||
pub x25: u64,
|
||||
pub x26: u64,
|
||||
pub x27: u64,
|
||||
pub x28: u64,
|
||||
pub x29: u64,
|
||||
pub x30: u64,
|
||||
pub pc: u64,
|
||||
pub cpsr: u64,
|
||||
pub spsr_el1: u64,
|
||||
pub spsr_fiq: u32,
|
||||
pub spsr_irq: u32,
|
||||
pub spsr_und: u32,
|
||||
pub spsr_abt: u32,
|
||||
pub sp_el0: u64,
|
||||
pub sp_el1: u64,
|
||||
pub elr_el1: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub struct VcpuGuestContext {
|
||||
pub flags: u32,
|
||||
pub user_regs: CpuUserRegs,
|
||||
pub sctlr: u64,
|
||||
pub ttbcr: u64,
|
||||
pub ttbr0: u64,
|
||||
pub ttbr1: u64,
|
||||
}
|
||||
|
||||
pub union VcpuGuestContextAny {
|
||||
pub value: VcpuGuestContext,
|
||||
}
|
||||
|
268
crates/xen/xenclient/src/arm64.rs
Normal file
268
crates/xen/xenclient/src/arm64.rs
Normal file
@ -0,0 +1,268 @@
|
||||
use crate::boot::{ArchBootSetup, BootImageInfo, BootSetup, BootState, DomainSegment};
|
||||
use crate::error::Result;
|
||||
use crate::sys::XEN_PAGE_SHIFT;
|
||||
use crate::Error;
|
||||
use log::trace;
|
||||
use xencall::sys::VcpuGuestContext;
|
||||
|
||||
pub const ARM_PAGE_SHIFT: u64 = 12;
|
||||
const ARM_PAGE_SIZE: u64 = 1 << ARM_PAGE_SHIFT;
|
||||
|
||||
const GUEST_RAM0_BASE: u64 = 0x40000000;
|
||||
const GUEST_RAM0_SIZE: u64 = 0xc0000000;
|
||||
const GUEST_RAM1_BASE: u64 = 0x0200000000;
|
||||
const GUEST_RAM1_SIZE: u64 = 0xfe00000000;
|
||||
|
||||
const GUEST_RAM_BANK_BASES: [u64; 2] = [GUEST_RAM0_BASE, GUEST_RAM1_BASE];
|
||||
const GUEST_RAM_BANK_SIZES: [u64; 2] = [GUEST_RAM0_SIZE, GUEST_RAM1_SIZE];
|
||||
|
||||
const LPAE_SHIFT: u64 = 9;
|
||||
const PFN_4K_SHIFT: u64 = 0;
|
||||
const PFN_2M_SHIFT: u64 = PFN_4K_SHIFT + LPAE_SHIFT;
|
||||
const PFN_1G_SHIFT: u64 = PFN_2M_SHIFT + LPAE_SHIFT;
|
||||
const PFN_512G_SHIFT: u64 = PFN_1G_SHIFT + LPAE_SHIFT;
|
||||
|
||||
const PSR_FIQ_MASK: u64 = 1 << 6; /* Fast Interrupt mask */
|
||||
const PSR_IRQ_MASK: u64 = 1 << 7; /* Interrupt mask */
|
||||
const PSR_ABT_MASK: u64 = 1 << 8; /* Asynchronous Abort mask */
|
||||
const PSR_MODE_EL1H: u64 = 0x05;
|
||||
const PSR_GUEST64_INIT: u64 = PSR_ABT_MASK | PSR_FIQ_MASK | PSR_IRQ_MASK | PSR_MODE_EL1H;
|
||||
|
||||
pub struct Arm64BootSetup {}
|
||||
|
||||
impl Default for Arm64BootSetup {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Arm64BootSetup {
|
||||
pub fn new() -> Arm64BootSetup {
|
||||
Arm64BootSetup {}
|
||||
}
|
||||
|
||||
fn populate_one_size(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
pfn_shift: u64,
|
||||
base_pfn: u64,
|
||||
pfn_count: u64,
|
||||
extents: &mut [u64],
|
||||
) -> Result<u64> {
|
||||
let mask = (1u64 << pfn_shift) - 1;
|
||||
let next_shift = pfn_shift + LPAE_SHIFT;
|
||||
let next_mask = (1u64 << next_shift) - 1;
|
||||
let next_boundary = (base_pfn + (1 << next_shift)) - 1;
|
||||
|
||||
let mut end_pfn = base_pfn + pfn_count;
|
||||
|
||||
if pfn_shift == PFN_512G_SHIFT {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
if (base_pfn & next_mask) != 0 && end_pfn > next_boundary {
|
||||
end_pfn = next_boundary;
|
||||
}
|
||||
|
||||
if (mask & base_pfn) != 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let count = (end_pfn - base_pfn) >> pfn_shift;
|
||||
|
||||
if count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
for i in 0..count {
|
||||
extents[i as usize] = base_pfn + (i << pfn_shift);
|
||||
}
|
||||
|
||||
let result_extents = setup.call.populate_physmap(
|
||||
setup.domid,
|
||||
count,
|
||||
pfn_shift as u32,
|
||||
0,
|
||||
&extents[0usize..count as usize],
|
||||
)?;
|
||||
slice_copy::copy(extents, &result_extents);
|
||||
Ok((result_extents.len() as u64) << pfn_shift)
|
||||
}
|
||||
|
||||
fn populate_guest_memory(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
base_pfn: u64,
|
||||
pfn_count: u64,
|
||||
) -> Result<()> {
|
||||
let mut extents = vec![0u64; 1024 * 1024];
|
||||
|
||||
for pfn in 0..extents.len() {
|
||||
let mut allocsz = (1024 * 1024).min(pfn_count - pfn as u64);
|
||||
allocsz = self.populate_one_size(
|
||||
setup,
|
||||
PFN_512G_SHIFT,
|
||||
base_pfn + pfn as u64,
|
||||
allocsz,
|
||||
&mut extents,
|
||||
)?;
|
||||
if allocsz > 0 {
|
||||
continue;
|
||||
}
|
||||
allocsz = self.populate_one_size(
|
||||
setup,
|
||||
PFN_1G_SHIFT,
|
||||
base_pfn + pfn as u64,
|
||||
allocsz,
|
||||
&mut extents,
|
||||
)?;
|
||||
if allocsz > 0 {
|
||||
continue;
|
||||
}
|
||||
allocsz = self.populate_one_size(
|
||||
setup,
|
||||
PFN_2M_SHIFT,
|
||||
base_pfn + pfn as u64,
|
||||
allocsz,
|
||||
&mut extents,
|
||||
)?;
|
||||
if allocsz > 0 {
|
||||
continue;
|
||||
}
|
||||
allocsz = self.populate_one_size(
|
||||
setup,
|
||||
PFN_4K_SHIFT,
|
||||
base_pfn + pfn as u64,
|
||||
allocsz,
|
||||
&mut extents,
|
||||
)?;
|
||||
if allocsz == 0 {
|
||||
return Err(Error::MemorySetupFailed);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ArchBootSetup for Arm64BootSetup {
|
||||
fn page_size(&mut self) -> u64 {
|
||||
ARM_PAGE_SIZE
|
||||
}
|
||||
|
||||
fn page_shift(&mut self) -> u64 {
|
||||
ARM_PAGE_SHIFT
|
||||
}
|
||||
|
||||
fn setup_shared_info(&mut self, _: &mut BootSetup, _: u64) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_start_info(&mut self, _: &mut BootSetup, _: &BootState, _: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn meminit(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
total_pages: u64,
|
||||
kernel_segment: &DomainSegment,
|
||||
initrd_segment: &Option<DomainSegment>,
|
||||
) -> Result<()> {
|
||||
setup.call.claim_pages(setup.domid, total_pages)?;
|
||||
let mut ramsize = total_pages << XEN_PAGE_SHIFT;
|
||||
|
||||
let bankbase = GUEST_RAM_BANK_BASES;
|
||||
let bankmax = GUEST_RAM_BANK_SIZES;
|
||||
|
||||
let kernbase = kernel_segment.vstart;
|
||||
let kernend = BootSetup::round_up(kernel_segment.size, 21);
|
||||
let dtb = setup.dtb.as_ref();
|
||||
let dtb_size = dtb.map(|blob| BootSetup::round_up(blob.len() as u64, XEN_PAGE_SHIFT));
|
||||
let ramdisk_size = initrd_segment
|
||||
.as_ref()
|
||||
.map(|segment| BootSetup::round_up(segment.size, XEN_PAGE_SHIFT));
|
||||
let modsize = dtb_size.unwrap_or(0) + ramdisk_size.unwrap_or(0);
|
||||
let ram128mb = bankbase[0] + (128 << 20);
|
||||
|
||||
let mut rambank_size: [u64; 2] = [0, 0];
|
||||
for i in 0..2 {
|
||||
let size = if ramsize > bankmax[i] {
|
||||
bankmax[i]
|
||||
} else {
|
||||
ramsize
|
||||
};
|
||||
ramsize -= size;
|
||||
rambank_size[i] = size >> XEN_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
for i in 0..2 {
|
||||
let size = if ramsize > bankmax[i] {
|
||||
bankmax[i]
|
||||
} else {
|
||||
ramsize
|
||||
};
|
||||
ramsize -= size;
|
||||
rambank_size[i] = size >> XEN_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
for i in 0..2 {
|
||||
self.populate_guest_memory(setup, bankbase[i] >> XEN_PAGE_SHIFT, rambank_size[i])?;
|
||||
}
|
||||
|
||||
let bank0end = bankbase[0] + (rambank_size[0] << XEN_PAGE_SHIFT);
|
||||
let _modbase = if bank0end >= ram128mb + modsize && kernend < ram128mb {
|
||||
ram128mb
|
||||
} else if bank0end - modsize > kernend {
|
||||
bank0end - modsize
|
||||
} else if kernbase - bankbase[0] > modsize {
|
||||
kernbase - modsize
|
||||
} else {
|
||||
return Err(Error::MemorySetupFailed);
|
||||
};
|
||||
setup.call.claim_pages(setup.domid, 0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bootlate(&mut self, _: &mut BootSetup, _: &mut BootState) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vcpu(&mut self, setup: &mut BootSetup, state: &mut BootState) -> Result<()> {
|
||||
let mut vcpu = VcpuGuestContext::default();
|
||||
vcpu.user_regs.pc = state.image_info.virt_entry;
|
||||
vcpu.user_regs.x0 = 0xffffffff;
|
||||
vcpu.user_regs.x1 = 0;
|
||||
vcpu.user_regs.x2 = 0;
|
||||
vcpu.user_regs.x3 = 0;
|
||||
vcpu.sctlr = 0x00c50078;
|
||||
vcpu.ttbr0 = 0;
|
||||
vcpu.ttbr1 = 0;
|
||||
vcpu.ttbcr = 0;
|
||||
vcpu.user_regs.cpsr = PSR_GUEST64_INIT;
|
||||
vcpu.flags = 1 << 0; // VGCF_ONLINE
|
||||
trace!("vcpu context: {:?}", vcpu);
|
||||
setup.call.set_vcpu_context(setup.domid, 0, &vcpu)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn alloc_p2m_segment(
|
||||
&mut self,
|
||||
_: &mut BootSetup,
|
||||
_: &BootImageInfo,
|
||||
) -> Result<Option<DomainSegment>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn alloc_page_tables(
|
||||
&mut self,
|
||||
_: &mut BootSetup,
|
||||
_: &BootImageInfo,
|
||||
) -> Result<Option<DomainSegment>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn setup_page_tables(&mut self, _: &mut BootSetup, _: &mut BootState) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ use libc::munmap;
|
||||
use log::debug;
|
||||
use slice_copy::copy;
|
||||
|
||||
use crate::mem::ARCH_PAGE_SHIFT;
|
||||
use std::ffi::c_void;
|
||||
use std::slice;
|
||||
use xencall::XenCall;
|
||||
@ -37,6 +38,7 @@ pub struct BootSetup<'a> {
|
||||
pub(crate) pfn_alloc_end: u64,
|
||||
pub(crate) virt_pgtab_end: u64,
|
||||
pub(crate) total_pages: u64,
|
||||
pub(crate) dtb: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -46,6 +48,7 @@ pub struct DomainSegment {
|
||||
pub pfn: u64,
|
||||
pub(crate) addr: u64,
|
||||
pub(crate) size: u64,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) pages: u64,
|
||||
}
|
||||
|
||||
@ -56,8 +59,8 @@ pub struct BootState {
|
||||
pub xenstore_segment: DomainSegment,
|
||||
pub console_segment: DomainSegment,
|
||||
pub boot_stack_segment: DomainSegment,
|
||||
pub p2m_segment: DomainSegment,
|
||||
pub page_table_segment: DomainSegment,
|
||||
pub p2m_segment: Option<DomainSegment>,
|
||||
pub page_table_segment: Option<DomainSegment>,
|
||||
pub image_info: BootImageInfo,
|
||||
pub shared_info_frame: u64,
|
||||
pub initrd_segment: DomainSegment,
|
||||
@ -75,12 +78,30 @@ impl BootSetup<'_> {
|
||||
pfn_alloc_end: 0,
|
||||
virt_pgtab_end: 0,
|
||||
total_pages: 0,
|
||||
dtb: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_memory(&mut self, arch: &mut dyn ArchBootSetup, total_pages: u64) -> Result<()> {
|
||||
fn initialize_memory(
|
||||
&mut self,
|
||||
arch: &mut dyn ArchBootSetup,
|
||||
total_pages: u64,
|
||||
kernel_segment: &DomainSegment,
|
||||
initrd_segment: &Option<DomainSegment>,
|
||||
) -> Result<()> {
|
||||
self.call.set_address_size(self.domid, 64)?;
|
||||
arch.meminit(self, total_pages)?;
|
||||
arch.meminit(self, total_pages, kernel_segment, initrd_segment)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_hypercall_page(&mut self, image_info: &BootImageInfo) -> Result<()> {
|
||||
if image_info.virt_hypercall == XEN_UNSET_ADDR {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pfn = (image_info.virt_hypercall - image_info.virt_base) >> ARCH_PAGE_SHIFT;
|
||||
let mfn = self.phys.p2m[pfn as usize];
|
||||
self.call.hypercall_init(self.domid, mfn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -94,18 +115,22 @@ impl BootSetup<'_> {
|
||||
) -> Result<BootState> {
|
||||
debug!("initialize max_vcpus={:?} mem_mb={:?}", max_vcpus, mem_mb);
|
||||
|
||||
let total_pages = mem_mb << (20 - arch.page_shift());
|
||||
self.initialize_memory(arch, total_pages)?;
|
||||
|
||||
let image_info = image_loader.parse()?;
|
||||
debug!("initialize image_info={:?}", image_info);
|
||||
self.virt_alloc_end = image_info.virt_base;
|
||||
let kernel_segment = self.load_kernel_segment(arch, image_loader, &image_info)?;
|
||||
let mut initrd_segment: Option<DomainSegment> = None;
|
||||
if !image_info.unmapped_initrd {
|
||||
initrd_segment = Some(self.alloc_module(arch, initrd)?);
|
||||
}
|
||||
let total_pages = mem_mb << (20 - arch.page_shift());
|
||||
self.initialize_memory(arch, total_pages, &kernel_segment, &initrd_segment)?;
|
||||
|
||||
self.virt_alloc_end = image_info.virt_base;
|
||||
let mut p2m_segment: Option<DomainSegment> = None;
|
||||
if image_info.virt_p2m_base >= image_info.virt_base
|
||||
|| (image_info.virt_p2m_base & ((1 << arch.page_shift()) - 1)) != 0
|
||||
{
|
||||
p2m_segment = Some(arch.alloc_p2m_segment(self, &image_info)?);
|
||||
p2m_segment = arch.alloc_p2m_segment(self, &image_info)?;
|
||||
}
|
||||
let start_info_segment = self.alloc_page(arch)?;
|
||||
let xenstore_segment = self.alloc_page(arch)?;
|
||||
@ -117,16 +142,12 @@ impl BootSetup<'_> {
|
||||
self.alloc_padding_pages(arch, self.virt_pgtab_end)?;
|
||||
}
|
||||
|
||||
let mut initrd_segment: Option<DomainSegment> = None;
|
||||
if !image_info.unmapped_initrd {
|
||||
initrd_segment = Some(self.alloc_module(arch, initrd)?);
|
||||
}
|
||||
if p2m_segment.is_none() {
|
||||
let mut segment = arch.alloc_p2m_segment(self, &image_info)?;
|
||||
segment.vstart = image_info.virt_p2m_base;
|
||||
p2m_segment = Some(segment);
|
||||
if let Some(mut segment) = arch.alloc_p2m_segment(self, &image_info)? {
|
||||
segment.vstart = image_info.virt_p2m_base;
|
||||
p2m_segment = Some(segment);
|
||||
}
|
||||
}
|
||||
let p2m_segment = p2m_segment.unwrap();
|
||||
|
||||
if image_info.unmapped_initrd {
|
||||
initrd_segment = Some(self.alloc_module(arch, initrd)?);
|
||||
@ -164,7 +185,7 @@ impl BootSetup<'_> {
|
||||
state.shared_info_frame = shared_info_frame;
|
||||
arch.setup_page_tables(self, state)?;
|
||||
arch.setup_start_info(self, state, cmdline)?;
|
||||
arch.setup_hypercall_page(self, &state.image_info)?;
|
||||
self.setup_hypercall_page(&state.image_info)?;
|
||||
arch.bootlate(self, state)?;
|
||||
arch.setup_shared_info(self, state.shared_info_frame)?;
|
||||
arch.vcpu(self, state)?;
|
||||
@ -219,6 +240,7 @@ impl BootSetup<'_> {
|
||||
addr | mask
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) fn bits_to_mask(bits: u64) -> u64 {
|
||||
(1 << bits) - 1
|
||||
}
|
||||
@ -243,6 +265,7 @@ impl BootSetup<'_> {
|
||||
pfn: self.pfn_alloc_end,
|
||||
addr: 0,
|
||||
size,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pages,
|
||||
};
|
||||
|
||||
@ -274,6 +297,7 @@ impl BootSetup<'_> {
|
||||
pfn,
|
||||
addr: 0,
|
||||
size: 0,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pages: 1,
|
||||
})
|
||||
}
|
||||
@ -324,13 +348,13 @@ pub trait ArchBootSetup {
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
) -> Result<DomainSegment>;
|
||||
) -> Result<Option<DomainSegment>>;
|
||||
|
||||
fn alloc_page_tables(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
) -> Result<DomainSegment>;
|
||||
) -> Result<Option<DomainSegment>>;
|
||||
|
||||
fn setup_page_tables(&mut self, setup: &mut BootSetup, state: &mut BootState) -> Result<()>;
|
||||
|
||||
@ -343,13 +367,13 @@ pub trait ArchBootSetup {
|
||||
|
||||
fn setup_shared_info(&mut self, setup: &mut BootSetup, shared_info_frame: u64) -> Result<()>;
|
||||
|
||||
fn setup_hypercall_page(
|
||||
fn meminit(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
total_pages: u64,
|
||||
kernel_segment: &DomainSegment,
|
||||
initrd_segment: &Option<DomainSegment>,
|
||||
) -> Result<()>;
|
||||
|
||||
fn meminit(&mut self, setup: &mut BootSetup, total_pages: u64) -> Result<()>;
|
||||
fn bootlate(&mut self, setup: &mut BootSetup, state: &mut BootState) -> Result<()>;
|
||||
fn vcpu(&mut self, setup: &mut BootSetup, state: &mut BootState) -> Result<()>;
|
||||
}
|
||||
|
@ -3,12 +3,18 @@ pub mod elfloader;
|
||||
pub mod error;
|
||||
pub mod mem;
|
||||
pub mod sys;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod x86;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub mod arm64;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::arm64::Arm64BootSetup;
|
||||
use crate::boot::BootSetup;
|
||||
use crate::elfloader::ElfImageLoader;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::x86::X86BootSetup;
|
||||
use log::{trace, warn};
|
||||
|
||||
use std::fs::read;
|
||||
@ -17,7 +23,7 @@ use std::str::FromStr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
use xencall::sys::CreateDomain;
|
||||
use xencall::sys::{CreateDomain, XEN_DOMCTL_CDF_HVM_GUEST};
|
||||
use xencall::XenCall;
|
||||
use xenstore::{
|
||||
XsPermission, XsdClient, XsdInterface, XS_PERM_NONE, XS_PERM_READ, XS_PERM_READ_WRITE,
|
||||
@ -92,8 +98,11 @@ impl XenClient {
|
||||
pub async fn create(&mut self, config: &DomainConfig<'_>) -> Result<u32> {
|
||||
let domain = CreateDomain {
|
||||
max_vcpus: config.max_vcpus,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
flags: XEN_DOMCTL_CDF_HVM_GUEST,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let domid = self.call.create_domain(domain)?;
|
||||
match self.init(domid, &domain, config).await {
|
||||
Ok(_) => Ok(domid),
|
||||
@ -233,7 +242,10 @@ impl XenClient {
|
||||
|
||||
{
|
||||
let mut boot = BootSetup::new(&self.call, domid);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let mut arch = X86BootSetup::new();
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let mut arch = Arm64BootSetup::new();
|
||||
let initrd = read(config.initrd_path)?;
|
||||
let mut state = boot.initialize(
|
||||
&mut arch,
|
||||
|
@ -5,7 +5,11 @@ use libc::munmap;
|
||||
use log::debug;
|
||||
use std::ffi::c_void;
|
||||
|
||||
use crate::x86::X86_PAGE_SHIFT;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub(crate) use crate::arm64::ARM_PAGE_SHIFT as ARCH_PAGE_SHIFT;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) use crate::x86::X86_PAGE_SHIFT as ARCH_PAGE_SHIFT;
|
||||
|
||||
use xencall::sys::MmapEntry;
|
||||
use xencall::XenCall;
|
||||
|
||||
@ -65,7 +69,7 @@ impl PhysicalPages<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(page.ptr + ((pfn - page.pfn) << X86_PAGE_SHIFT));
|
||||
return Ok(page.ptr + ((pfn - page.pfn) << ARCH_PAGE_SHIFT));
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
@ -148,7 +152,7 @@ impl PhysicalPages<'_> {
|
||||
unsafe {
|
||||
let err = munmap(
|
||||
page.ptr as *mut c_void,
|
||||
(page.count << X86_PAGE_SHIFT) as usize,
|
||||
(page.count << ARCH_PAGE_SHIFT) as usize,
|
||||
);
|
||||
if err != 0 {
|
||||
return Err(Error::UnmapFailed);
|
||||
@ -169,11 +173,11 @@ impl PhysicalPages<'_> {
|
||||
unsafe {
|
||||
let err = munmap(
|
||||
page.ptr as *mut c_void,
|
||||
(page.count << X86_PAGE_SHIFT) as usize,
|
||||
(page.count << ARCH_PAGE_SHIFT) as usize,
|
||||
);
|
||||
debug!(
|
||||
"unmapped {:#x} foreign bytes at {:#x}",
|
||||
(page.count << X86_PAGE_SHIFT) as usize,
|
||||
(page.count << ARCH_PAGE_SHIFT) as usize,
|
||||
page.ptr
|
||||
);
|
||||
if err != 0 {
|
||||
|
@ -291,7 +291,7 @@ impl ArchBootSetup for X86BootSetup {
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
) -> Result<DomainSegment> {
|
||||
) -> Result<Option<DomainSegment>> {
|
||||
let mut p2m_alloc_size =
|
||||
((setup.phys.p2m_size() * 8) + X86_PAGE_SIZE - 1) & !(X86_PAGE_SIZE - 1);
|
||||
let from = image_info.virt_p2m_base;
|
||||
@ -310,14 +310,14 @@ impl ArchBootSetup for X86BootSetup {
|
||||
self.table.mappings_count += 1;
|
||||
p2m_alloc_size += (pgtables << X86_PAGE_SHIFT) as u64;
|
||||
let p2m_segment = setup.alloc_segment(self, 0, p2m_alloc_size)?;
|
||||
Ok(p2m_segment)
|
||||
Ok(Some(p2m_segment))
|
||||
}
|
||||
|
||||
fn alloc_page_tables(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
) -> Result<DomainSegment> {
|
||||
) -> Result<Option<DomainSegment>> {
|
||||
let mut extra_pages = 1;
|
||||
extra_pages += (512 * 1024) / X86_PAGE_SIZE;
|
||||
let mut pages = extra_pages;
|
||||
@ -345,7 +345,7 @@ impl ArchBootSetup for X86BootSetup {
|
||||
"alloc_page_tables table={:?} segment={:?}",
|
||||
self.table, segment
|
||||
);
|
||||
Ok(segment)
|
||||
Ok(Some(segment))
|
||||
}
|
||||
|
||||
fn setup_page_tables(&mut self, setup: &mut BootSetup, state: &mut BootState) -> Result<()> {
|
||||
@ -461,22 +461,13 @@ impl ArchBootSetup for X86BootSetup {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_hypercall_page(
|
||||
fn meminit(
|
||||
&mut self,
|
||||
setup: &mut BootSetup,
|
||||
image_info: &BootImageInfo,
|
||||
total_pages: u64,
|
||||
kernel_segment: &DomainSegment,
|
||||
initrd_segment: &Option<DomainSegment>,
|
||||
) -> Result<()> {
|
||||
if image_info.virt_hypercall == XEN_UNSET_ADDR {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pfn = (image_info.virt_hypercall - image_info.virt_base) >> X86_PAGE_SHIFT;
|
||||
let mfn = setup.phys.p2m[pfn as usize];
|
||||
setup.call.hypercall_init(setup.domid, mfn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn meminit(&mut self, setup: &mut BootSetup, total_pages: u64) -> Result<()> {
|
||||
setup.call.claim_pages(setup.domid, total_pages)?;
|
||||
let mut vmemranges: Vec<VmemRange> = Vec::new();
|
||||
let stub = VmemRange {
|
||||
|
5771
kernel/krata-arm64.config
Normal file
5771
kernel/krata-arm64.config
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user