mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
uHyve should work now
This commit is contained in:
parent
bb0e1f2a36
commit
0037839174
6 changed files with 57 additions and 43 deletions
|
@ -110,7 +110,7 @@ impl Entry {
|
|||
|
||||
// return the flags bits
|
||||
pub fn get_flags(&self) -> FlagBits {
|
||||
FlagBits { flags: self.flags_limit_h & 0x0F }
|
||||
FlagBits { flags: (self.flags_limit_h & 0xF0) >> 4 }
|
||||
}
|
||||
|
||||
// convert the struct to an unsigned integer
|
||||
|
|
|
@ -1497,45 +1497,35 @@ impl Clone for kvm_cpuid_entry2 {
|
|||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy)]
|
||||
pub struct kvm_cpuid2 {
|
||||
#[derive(Copy)]
|
||||
pub struct kvm_cpuid2_header {
|
||||
pub nent: __u32,
|
||||
pub padding: __u32,
|
||||
pub entries: [kvm_cpuid_entry2; 4]
|
||||
}
|
||||
|
||||
impl Clone for kvm_cpuid2_header {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct kvm_cpuid2 {
|
||||
pub header: kvm_cpuid2_header,
|
||||
pub data: [kvm_cpuid_entry2; 40]
|
||||
}
|
||||
|
||||
impl kvm_cpuid2 {
|
||||
pub fn empty() -> kvm_cpuid2 {
|
||||
kvm_cpuid2 {
|
||||
nent: 4,
|
||||
padding: 0,
|
||||
entries: [kvm_cpuid_entry2::empty(); 4]
|
||||
header: kvm_cpuid2_header {
|
||||
nent: 40,
|
||||
padding: 0
|
||||
},
|
||||
data: [kvm_cpuid_entry2::empty();40]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bindgen_test_layout_kvm_cpuid2() {
|
||||
assert_eq!(::std::mem::size_of::<kvm_cpuid2>() , 8usize , concat ! (
|
||||
"Size of: " , stringify ! ( kvm_cpuid2 ) ));
|
||||
assert_eq! (::std::mem::align_of::<kvm_cpuid2>() , 4usize , concat ! (
|
||||
"Alignment of " , stringify ! ( kvm_cpuid2 ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const kvm_cpuid2 ) ) . nent as * const _ as
|
||||
usize } , 0usize , concat ! (
|
||||
"Alignment of field: " , stringify ! ( kvm_cpuid2 ) , "::" ,
|
||||
stringify ! ( nent ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const kvm_cpuid2 ) ) . padding as * const _ as
|
||||
usize } , 4usize , concat ! (
|
||||
"Alignment of field: " , stringify ! ( kvm_cpuid2 ) , "::" ,
|
||||
stringify ! ( padding ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const kvm_cpuid2 ) ) . entries as * const _ as
|
||||
usize } , 8usize , concat ! (
|
||||
"Alignment of field: " , stringify ! ( kvm_cpuid2 ) , "::" ,
|
||||
stringify ! ( entries ) ));
|
||||
}
|
||||
impl Clone for kvm_cpuid2 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
|
|
@ -54,6 +54,10 @@ impl Syscall {
|
|||
unsafe {
|
||||
let ref run = *(mem.as_ptr() as *const kvm_run);
|
||||
|
||||
debug!("Exit reason {}", run.exit_reason);
|
||||
|
||||
|
||||
|
||||
if run.exit_reason != KVM_EXIT_IO {
|
||||
return Syscall::Other(mem.as_ptr() as *const kvm_run);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use uhyve::vm::VirtualMachine;
|
|||
/// ioctl! macro and need to be wrapped further to provide a safe interface.
|
||||
pub mod ioctl {
|
||||
use std::mem;
|
||||
use uhyve::kvm_header::{KVMIO, kvm_msr_list, kvm_cpuid2, kvm_memory_region, kvm_dirty_log, kvm_memory_alias, kvm_userspace_memory_region, kvm_regs,kvm_sregs};
|
||||
use uhyve::kvm_header::{KVMIO, kvm_msr_list, kvm_cpuid2_header, kvm_memory_region, kvm_dirty_log, kvm_memory_alias, kvm_userspace_memory_region, kvm_regs,kvm_sregs};
|
||||
|
||||
ioctl!(get_version with io!(KVMIO, 0x00));
|
||||
ioctl!(create_vm with io!(KVMIO, 0x01));
|
||||
|
@ -23,9 +23,9 @@ pub mod ioctl {
|
|||
ioctl!(check_extension with io!(KVMIO, 0x03));
|
||||
ioctl!(get_vcpu_mmap_size with io!(KVMIO, 0x04));
|
||||
|
||||
ioctl!(read get_supported_cpuid with KVMIO, 0x05; kvm_cpuid2);
|
||||
ioctl!(read get_emulated_cpuid with KVMIO,0x09; kvm_cpuid2);
|
||||
ioctl!(write set_cpuid2 with KVMIO, 0x90; kvm_cpuid2);
|
||||
ioctl!(readwrite get_supported_cpuid with KVMIO, 0x05; kvm_cpuid2_header);
|
||||
ioctl!(read get_emulated_cpuid with KVMIO,0x09; kvm_cpuid2_header);
|
||||
ioctl!(write set_cpuid2 with KVMIO, 0x90; kvm_cpuid2_header);
|
||||
|
||||
ioctl!(create_vcpu with io!(KVMIO, 0x41));
|
||||
ioctl!(read get_dirty_log with KVMIO, 0x42; kvm_dirty_log);
|
||||
|
|
|
@ -7,7 +7,7 @@ use memmap::{Mmap, Protection};
|
|||
use errno::errno;
|
||||
|
||||
use uhyve;
|
||||
use uhyve::kvm_header::{kvm_sregs, kvm_regs, kvm_segment, kvm_cpuid2};
|
||||
use uhyve::kvm_header::{kvm_sregs, kvm_regs, kvm_segment, kvm_cpuid2,kvm_cpuid2_header};
|
||||
use uhyve::{Result, Error, NameIOCTL};
|
||||
use uhyve::gdt;
|
||||
use uhyve::proto;
|
||||
|
@ -30,7 +30,7 @@ pub const X86_CR0_PE: u64 = (1 << 0);
|
|||
pub const X86_CR0_PG: u64 = (1 << 31);
|
||||
|
||||
/// Intel long mode page directory/table entries
|
||||
pub const X86_CR4_PAE: u64 = (1 << 0);
|
||||
pub const X86_CR4_PAE: u64 = (1u64 << 5);
|
||||
|
||||
/// Intel long mode page directory/table entries
|
||||
pub const X86_PDPT_P: u64 = (1 << 0);
|
||||
|
@ -76,11 +76,14 @@ impl VirtualCPU {
|
|||
cpu.setup_first(&mut mem)?;
|
||||
}
|
||||
|
||||
debug!("Initialize the register of {}", id);
|
||||
|
||||
let mut regs = kvm_regs::empty();
|
||||
regs.rip = entry;
|
||||
regs.rflags = 0x2;
|
||||
regs.rax = 2;
|
||||
regs.rbx = 2;
|
||||
|
||||
debug!("Initialize the register of {} with start address {:?}", id, entry);
|
||||
|
||||
cpu.set_regs(regs)?;
|
||||
|
||||
|
@ -131,7 +134,7 @@ impl VirtualCPU {
|
|||
debug!("Size {}", mem::size_of::<kvm_cpuid2>());
|
||||
|
||||
unsafe {
|
||||
uhyve::ioctl::get_supported_cpuid(self.kvm_fd, (&mut cpuid) as *mut kvm_cpuid2)
|
||||
uhyve::ioctl::get_supported_cpuid(self.kvm_fd, (&mut cpuid.header) as *mut kvm_cpuid2_header)
|
||||
.map_err(|x| Error::IOCTL(NameIOCTL::GetSupportedCpuID))?;
|
||||
}
|
||||
|
||||
|
@ -140,7 +143,7 @@ impl VirtualCPU {
|
|||
|
||||
pub fn set_cpuid2(&self, mut cpuid: kvm_cpuid2) -> Result<()> {
|
||||
unsafe {
|
||||
uhyve::ioctl::set_cpuid2(self.vm_fd, (&mut cpuid) as *mut kvm_cpuid2)
|
||||
uhyve::ioctl::set_cpuid2(self.vcpu_fd, (&mut cpuid.header) as *mut kvm_cpuid2_header)
|
||||
.map_err(|x| Error::IOCTL(NameIOCTL::SetCpuID2))?;
|
||||
}
|
||||
|
||||
|
@ -160,6 +163,8 @@ impl VirtualCPU {
|
|||
.map_err(|x| Error::IOCTL(NameIOCTL::Run))
|
||||
}?;
|
||||
|
||||
debug!("Run with {}", ret);
|
||||
|
||||
if ret == -1 {
|
||||
match errno().0 {
|
||||
libc::EINTR => { return Ok(ret); },
|
||||
|
@ -201,6 +206,8 @@ impl VirtualCPU {
|
|||
debug!("Set the system to 64bit");
|
||||
self.setup_system_64bit(&mut sregs)?;
|
||||
|
||||
debug!("SREGS {:?}", sregs);
|
||||
|
||||
self.set_sregs(sregs)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -219,9 +226,11 @@ impl VirtualCPU {
|
|||
unsafe {
|
||||
*(ptr.offset(gdt::BOOT_NULL)) = gdt_null.as_u64();
|
||||
*(ptr.offset(gdt::BOOT_CODE)) = gdt_code.as_u64();
|
||||
*(ptr.offset(gdt::BOOT_DATA)) = gdt_code.as_u64();
|
||||
*(ptr.offset(gdt::BOOT_DATA)) = gdt_data.as_u64();
|
||||
}
|
||||
|
||||
debug!("{} {} {}", gdt_null.as_u64(), gdt_code.as_u64(), gdt_data.as_u64());
|
||||
|
||||
gdt_code.apply_to_kvm(gdt::BOOT_CODE, &mut code_seg);
|
||||
gdt_data.apply_to_kvm(gdt::BOOT_DATA, &mut data_seg);
|
||||
|
||||
|
@ -234,6 +243,8 @@ impl VirtualCPU {
|
|||
sregs.gs = data_seg;
|
||||
sregs.ss = data_seg;
|
||||
|
||||
debug!("Code: {:#?},\n Data: {:#?}", code_seg,data_seg);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn setup_system_page_table(&self, sregs: &mut kvm_sregs, mem: &mut [u8]) -> Result<()> {
|
||||
|
@ -252,7 +263,9 @@ impl VirtualCPU {
|
|||
|
||||
*pml4 = (BOOT_PDPTE as u64) | (X86_PDPT_P | X86_PDPT_RW);
|
||||
*pdpte = (BOOT_PDE as u64) | (X86_PDPT_P | X86_PDPT_RW);
|
||||
|
||||
|
||||
println!("\n{}\n", *pdpte);
|
||||
|
||||
for i in 0..(GUEST_SIZE/GUEST_PAGE_SIZE) {
|
||||
*(pde.offset(i as isize)) = (i*GUEST_PAGE_SIZE) as u64 | (X86_PDPT_P | X86_PDPT_RW | X86_PDPT_PS);
|
||||
}
|
||||
|
@ -275,12 +288,13 @@ impl VirtualCPU {
|
|||
pub fn setup_cpuid(&self) -> Result<()> {
|
||||
let mut kvm_cpuid = self.get_supported_cpuid()?;
|
||||
|
||||
debug!("Supported CPUs {:?}", kvm_cpuid);
|
||||
debug!("Supported CPUs {:?}", kvm_cpuid.data.iter());
|
||||
|
||||
for entry in kvm_cpuid.entries.iter_mut() {
|
||||
for entry in kvm_cpuid.data.iter_mut() {
|
||||
match entry.function {
|
||||
1 => {
|
||||
entry.ecx |= 1u32 << 31; // propagate that we are running on a hypervisor
|
||||
entry.ecx = entry.ecx & !(1 << 21);
|
||||
entry.edx |= 1u32 << 5; // enable msr support
|
||||
},
|
||||
0x0A => {
|
||||
|
|
|
@ -77,19 +77,25 @@ impl VirtualMachine {
|
|||
debug!("Load segment with start addr {} and size {} to {}", header.paddr, header.filesz, header.offset);
|
||||
|
||||
vm_mem[vm_start..vm_end].copy_from_slice(&kernel_file[kernel_start..kernel_end]);
|
||||
|
||||
unsafe {
|
||||
libc::memset(vm_mem.as_mut_ptr().offset(vm_end as isize) as *mut libc::c_void, 0x00, (header.memsz - header.filesz) as usize);
|
||||
}
|
||||
|
||||
let ptr = vm_mem[vm_start..vm_end].as_mut_ptr();
|
||||
|
||||
unsafe {
|
||||
*(ptr.offset(0x08) as *mut u64) = header.paddr; // physical start addr
|
||||
*(ptr.offset(0x10) as *mut u64) = vm_mem_length; // physical size limit
|
||||
*(ptr.offset(0x18) as *mut u32) = utils::cpufreq()?; // CPU frequency
|
||||
*(ptr.offset(0x18) as *mut u32) = utils::cpufreq()? / 1000; // CPU frequency
|
||||
*(ptr.offset(0x24) as *mut u32) = 1; // number of used CPUs
|
||||
*(ptr.offset(0x30) as *mut u32) = 0; // apicid (?)
|
||||
*(ptr.offset(0x38) as *mut u64) = header.filesz; //
|
||||
*(ptr.offset(0x60) as *mut u32) = 1; // NUMA nodes
|
||||
*(ptr.offset(0x94) as *mut u32) = 1; // announce uhyve
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
debug!("Kernel loaded");
|
||||
|
|
Loading…
Add table
Reference in a new issue