1
0
Fork 0
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:
l_schmid 2017-05-11 23:11:00 +02:00
parent bb0e1f2a36
commit 0037839174
6 changed files with 57 additions and 43 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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 => {

View file

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