1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

The sregs are now set properly for all cpus.

This commit is contained in:
bytesnake 2017-06-10 22:58:23 +02:00
parent e7c08c271c
commit bb5800abbe
4 changed files with 44 additions and 47 deletions

View file

@ -22,7 +22,7 @@ pub fn mem_size() -> String {
}
pub fn mem_size_parsed() -> usize {
env::var("HERMIT_MEM").map(|x| utils::parse_mem(&x).unwrap_or(2*1000*1000)).unwrap_or(2*1000*1000)
env::var("HERMIT_MEM").map(|x| utils::parse_mem(&x).unwrap_or(512*1024*1024)).unwrap_or(512*1024*1024)
}
pub fn use_kvm() -> String {

View file

@ -58,6 +58,7 @@ pub enum Syscall {
Other(*const kvm_run)
}
#[derive(Debug)]
pub enum Return {
Continue,
Exit(i32)

View file

@ -75,38 +75,25 @@ impl VirtualCPU {
kvm_fd: kvm_fd, vm_fd: vm_fd, vcpu_fd: fd, id: id, file: file, run_mem: run_mem, mboot: mboot, guest_mem: mem.mut_ptr()
};
cpu.set_mp_state(kvm_mp_state { mp_state: KVM_MP_STATE_RUNNABLE })?;
if id == 0 {
debug!("Setup the first processor");
let mut mem = unsafe {
mem.as_mut_slice()
};
cpu.setup_first(&mut mem)?;
}
debug!("Initialize the register of {} with start address {:?}", id, entry);
debug!("Set the CPUID");
cpu.setup_cpuid()?;
debug!("Set MP state");
cpu.set_mp_state(kvm_mp_state { mp_state: KVM_MP_STATE_RUNNABLE })?;
debug!("Initialize the register of {} with start address {:?}", id, entry);
let mut regs = kvm_regs::empty();
regs.rip = entry;
regs.rflags = 0x2;
cpu.set_regs(regs)?;
Ok(cpu)
}
pub fn create_vcpu(fd: c_int, mut id: u32) -> Result<c_int> {
let a = (&mut id) as *mut u32 as *mut u8;
unsafe {
uhyve::ioctl::create_vcpu(fd, id as *mut u8)
.map_err(|_| Error::IOCTL(NameIOCTL::CreateVcpu))
@ -196,7 +183,10 @@ impl VirtualCPU {
}
unsafe {
proto::Syscall::from_mem(obj.run_mem.ptr(), obj.guest_mem).run(obj.guest_mem)
let a = proto::Syscall::from_mem(obj.run_mem.ptr(), obj.guest_mem).run(obj.guest_mem);
debug!("{:?}", a);
a
}
}
@ -209,7 +199,7 @@ impl VirtualCPU {
unsafe {
while volatile_load(wrapped.mboot.offset(0x20)) < wrapped.id {
thread::yield_now();
debug!("{} - {}", wrapped.id, volatile_load(wrapped.mboot.offset(0x20)));
//debug!("{} - {}", wrapped.id, volatile_load(wrapped.mboot.offset(0x20)));
}
volatile_store(wrapped.mboot.offset(0x30), wrapped.id);
@ -226,28 +216,21 @@ impl VirtualCPU {
child
}
pub fn setup_first(&self, mem: &mut [u8]) -> Result<()> {
// This is a fatal fault, so we will abort here
if self.id != 0 {
panic!("Shouldn't be called by any other processor than the first!");
}
pub fn init_sregs(&self) -> Result<kvm_sregs> {
let mut sregs = self.get_sregs()?;
debug!("Setup GDT");
self.setup_system_gdt(&mut sregs, mem, 0)?;
self.setup_system_gdt(&mut sregs, 0)?;
debug!("Setup the page table");
self.setup_system_page_table(&mut sregs, mem)?;
self.setup_system_page_table(&mut sregs)?;
debug!("Set the system to 64bit");
self.setup_system_64bit(&mut sregs)?;
self.set_sregs(sregs)?;
Ok(())
Ok(sregs)
}
pub fn setup_system_gdt(&self, sregs: &mut kvm_sregs, mem: &mut [u8], offset: u64) -> Result<()> {
pub fn setup_system_gdt(&self, sregs: &mut kvm_sregs, offset: u64) -> Result<()> {
let (mut data_seg, mut code_seg) = (kvm_segment::empty(), kvm_segment::empty());
// create the GDT entries
@ -256,8 +239,9 @@ impl VirtualCPU {
let gdt_data = gdt::Entry::new(0xC093, 0, 0xFFFFF);
// apply the new GDTs to our guest memory
let ptr = mem[offset as usize..].as_ptr() as *mut u64;
unsafe {
let ptr = self.guest_mem.offset(offset as isize) as *mut u64;
*(ptr.offset(gdt::BOOT_NULL)) = gdt_null.as_u64();
*(ptr.offset(gdt::BOOT_CODE)) = gdt_code.as_u64();
*(ptr.offset(gdt::BOOT_DATA)) = gdt_data.as_u64();
@ -277,16 +261,20 @@ impl VirtualCPU {
Ok(())
}
pub fn setup_system_page_table(&self, sregs: &mut kvm_sregs, mem: &mut [u8]) -> Result<()> {
let pml4 = mem[BOOT_PML4..].as_ptr() as *mut u64;
pub fn setup_system_page_table(&self, sregs: &mut kvm_sregs) -> Result<()> {
/*let pml4 = mem[BOOT_PML4..].as_ptr() as *mut u64;
let pdpte = mem[BOOT_PDPTE..].as_ptr() as *mut u64;
let pde = mem[BOOT_PDE..].as_ptr() as *mut u64;
let pde = mem[BOOT_PDE..].as_ptr() as *mut u64;*/
// TODO
//assert!((guest_size & (GUEST_PAGE_SIZE - 1)) == 0);
//assert!(guest_size <= (GUEST_PAGE_SIZE * 512));
unsafe {
let pml4 = self.guest_mem.offset(BOOT_PML4 as isize) as *mut u64;
let pdpte = self.guest_mem.offset(BOOT_PDPTE as isize) as *mut u64;
let pde = self.guest_mem.offset(BOOT_PDE as isize) as *mut u64;
libc::memset(pml4 as *mut c_void, 0x00, 4096);
libc::memset(pdpte as *mut c_void, 0x00, 4096);
libc::memset(pde as *mut c_void, 0x00, 4096);

View file

@ -13,7 +13,7 @@ use std::ffi::CStr;
use hermit::hermit_env;
use hermit::utils;
use hermit::uhyve;
use super::kvm_header::{kvm_userspace_memory_region, KVM_CAP_SYNC_MMU, KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE};
use super::kvm_header::{kvm_userspace_memory_region, KVM_CAP_SYNC_MMU, KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, kvm_sregs};
use super::{Result, Error, NameIOCTL};
use super::vcpu::VirtualCPU;
@ -29,7 +29,8 @@ pub struct VirtualMachine {
klog: Option<*const i8>,
mboot: Option<*mut u8>,
vcpus: Vec<VirtualCPU>,
num_cpus: u32
num_cpus: u32,
sregs: kvm_sregs
}
impl VirtualMachine {
@ -48,7 +49,7 @@ impl VirtualMachine {
unsafe { libc::mprotect((mem.mut_ptr() as *mut libc::c_void).offset(KVM_32BIT_GAP_START as isize), KVM_32BIT_GAP_START, libc::PROT_NONE); }
}
Ok(VirtualMachine { kvm_fd: kvm_fd, vm_fd: fd, mem: mem, elf_header: None, klog: None, vcpus: Vec::new(), mboot: None, num_cpus: num_cpus})
Ok(VirtualMachine { kvm_fd: kvm_fd, vm_fd: fd, mem: mem, elf_header: None, klog: None, vcpus: Vec::new(), mboot: None, num_cpus: num_cpus, sregs: kvm_sregs::default()})
}
/// Loads a kernel from path and initialite mem and elf_entry
@ -122,6 +123,7 @@ impl VirtualMachine {
/// Initialize the virtual machine
pub fn init(&mut self) -> Result<()> {
let mut identity_base: u64 = 0xfffbc000;
if let Ok(true) = self.check_extension(KVM_CAP_SYNC_MMU) {
identity_base = 0xfeffc000;
@ -155,7 +157,7 @@ impl VirtualMachine {
Ok(())
}
pub fn set_user_memory_region(&self, mut region: kvm_userspace_memory_region) -> Result<()> {
unsafe {
uhyve::ioctl::set_user_memory_region(self.vm_fd, (&mut region) as *mut kvm_userspace_memory_region)
@ -172,14 +174,14 @@ impl VirtualMachine {
pub fn check_extension(&self, mut extension: u32) -> Result<bool> {
unsafe {
uhyve::ioctl::check_extension(self.vm_fd, (&mut extension) as *mut u32 as *mut u8)
.map_err(|x| Error::IOCTL(NameIOCTL::CheckExtension)).map(|x| x == 1)
uhyve::ioctl::check_extension(self.vm_fd, extension as *mut u8)
.map_err(|x| Error::IOCTL(NameIOCTL::CheckExtension)).map(|x| x > 0)
}
}
pub fn set_tss_identity(&self, identity_base: u64) -> Result<()> {
unsafe {
uhyve::ioctl::set_identity_map_addr(self.kvm_fd, (&identity_base) as *const u64)
uhyve::ioctl::set_identity_map_addr(self.vm_fd, (&identity_base) as *const u64)
.map_err(|x| Error::IOCTL(NameIOCTL::SetTssIdentity)).map(|_| ())
}
}
@ -194,8 +196,14 @@ impl VirtualMachine {
pub fn create_vcpu(&mut self, id: u8) -> Result<()> {
let entry = self.elf_header.ok_or(Error::KernelNotLoaded)?.entry;
let cpu = VirtualCPU::new(self.kvm_fd, self.vm_fd, id, entry, &mut self.mem, self.mboot.unwrap())?;
let cpu = VirtualCPU::new(self.kvm_fd, self.vm_fd, id, entry, &mut self.mem,self.mboot.unwrap())?;
if id == 0 {
self.sregs = cpu.init_sregs()?;
}
cpu.set_sregs(self.sregs)?;
let id = id as usize;
self.vcpus.insert(id, cpu);