From 00378391741793394da2ea4334d2e9572c56f448 Mon Sep 17 00:00:00 2001 From: l_schmid Date: Thu, 11 May 2017 23:11:00 +0200 Subject: [PATCH] uHyve should work now --- tools/hermit_proxy/src/uhyve/gdt.rs | 2 +- tools/hermit_proxy/src/uhyve/kvm_header.rs | 46 +++++++++------------- tools/hermit_proxy/src/uhyve/proto.rs | 4 ++ tools/hermit_proxy/src/uhyve/uhyve.rs | 8 ++-- tools/hermit_proxy/src/uhyve/vcpu.rs | 32 ++++++++++----- tools/hermit_proxy/src/uhyve/vm.rs | 8 +++- 6 files changed, 57 insertions(+), 43 deletions(-) diff --git a/tools/hermit_proxy/src/uhyve/gdt.rs b/tools/hermit_proxy/src/uhyve/gdt.rs index e8e163f9b..a42adfd95 100644 --- a/tools/hermit_proxy/src/uhyve/gdt.rs +++ b/tools/hermit_proxy/src/uhyve/gdt.rs @@ -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 diff --git a/tools/hermit_proxy/src/uhyve/kvm_header.rs b/tools/hermit_proxy/src/uhyve/kvm_header.rs index c7c5da8b2..49fa3c508 100644 --- a/tools/hermit_proxy/src/uhyve/kvm_header.rs +++ b/tools/hermit_proxy/src/uhyve/kvm_header.rs @@ -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::() , 8usize , concat ! ( - "Size of: " , stringify ! ( kvm_cpuid2 ) )); - assert_eq! (::std::mem::align_of::() , 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 } } diff --git a/tools/hermit_proxy/src/uhyve/proto.rs b/tools/hermit_proxy/src/uhyve/proto.rs index 0a7a29541..1b37798cd 100644 --- a/tools/hermit_proxy/src/uhyve/proto.rs +++ b/tools/hermit_proxy/src/uhyve/proto.rs @@ -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); } diff --git a/tools/hermit_proxy/src/uhyve/uhyve.rs b/tools/hermit_proxy/src/uhyve/uhyve.rs index 00acb2bf5..c1caac4b3 100644 --- a/tools/hermit_proxy/src/uhyve/uhyve.rs +++ b/tools/hermit_proxy/src/uhyve/uhyve.rs @@ -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); diff --git a/tools/hermit_proxy/src/uhyve/vcpu.rs b/tools/hermit_proxy/src/uhyve/vcpu.rs index a87e125e9..6909caf4a 100644 --- a/tools/hermit_proxy/src/uhyve/vcpu.rs +++ b/tools/hermit_proxy/src/uhyve/vcpu.rs @@ -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::()); 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 => { diff --git a/tools/hermit_proxy/src/uhyve/vm.rs b/tools/hermit_proxy/src/uhyve/vm.rs index 998bdf302..a40c2cd54 100644 --- a/tools/hermit_proxy/src/uhyve/vm.rs +++ b/tools/hermit_proxy/src/uhyve/vm.rs @@ -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");