Skip to content

Commit

Permalink
Merge pull request #452 from hermitcore/uhypercall
Browse files Browse the repository at this point in the history
Move Hypercall interface in distinct crate
  • Loading branch information
jounathaen authored Jun 2, 2023
2 parents a696cb1 + dc7da20 commit bc902db
Show file tree
Hide file tree
Showing 12 changed files with 520 additions and 332 deletions.
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[workspace]
exclude = ["tests/test-kernels", "rusty-hermit", "rusty-hermit/*", "libhermit-rs"]

[package]
name = "uhyve"
version = "0.2.2"
Expand Down Expand Up @@ -50,6 +53,7 @@ libc = "0.2"
log = "0.4"
thiserror = "1.0"
time = "0.3"
uhyve-interface = { path = "./uhyve-interface" }

rftrace = { version = "0.1", optional = true }
rftrace-frontend = { version = "0.1", optional = true }
Expand Down
20 changes: 0 additions & 20 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,3 @@ pub const UHYVE_QUEUE_SIZE: usize = 8;
pub const UHYVE_IRQ_NET: u32 = 11;

pub const GUEST_PAGE_SIZE: u64 = 0x200000; /* 2 MB pages in guest */

pub const UHYVE_PORT_WRITE: u16 = 0x400;
pub const UHYVE_PORT_OPEN: u16 = 0x440;
pub const UHYVE_PORT_CLOSE: u16 = 0x480;
pub const UHYVE_PORT_READ: u16 = 0x500;
pub const UHYVE_PORT_EXIT: u16 = 0x540;
pub const UHYVE_PORT_LSEEK: u16 = 0x580;

// Networkports
pub const UHYVE_PORT_NETWRITE: u16 = 0x640;
pub const UHYVE_PORT_NETREAD: u16 = 0x680;
pub const UHYVE_PORT_NETSTAT: u16 = 0x700;

/* Ports and data structures for uhyve command line arguments and envp
* forwarding */
pub const UHYVE_PORT_CMDSIZE: u16 = 0x740;
pub const UHYVE_PORT_CMDVAL: u16 = 0x780;

pub const UHYVE_UART_PORT: u16 = 0x800;
pub const UHYVE_PORT_UNLINK: u16 = 0x840;
177 changes: 63 additions & 114 deletions src/linux/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{

use kvm_bindings::*;
use kvm_ioctls::{VcpuExit, VcpuFd};
use uhyve_interface::{Hypercall, UHYVE_PORT_NETWRITE};
use x86_64::{
registers::control::{Cr0Flags, Cr4Flags},
structures::paging::PageTableFlags,
Expand All @@ -15,10 +16,7 @@ use x86_64::{
use crate::{
consts::*,
linux::{virtio::*, KVM},
vm::{
HypervisorResult, SysClose, SysCmdsize, SysCmdval, SysExit, SysLseek, SysOpen, SysRead,
SysUnlink, SysWrite, VcpuStopReason, VirtualCPU,
},
vm::{HypervisorResult, VcpuStopReason, VirtualCPU},
};

const CPUID_EXT_HYPERVISOR: u32 = 1 << 31;
Expand Down Expand Up @@ -363,118 +361,69 @@ impl VirtualCPU for UhyveCPU {
}
},
VcpuExit::IoOut(port, addr) => {
match port {
UHYVE_UART_PORT => {
self.uart(addr)?;
}
UHYVE_PORT_CMDSIZE => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let syssize = unsafe {
&mut *(self.host_address(data_addr) as *mut SysCmdsize)
};
self.cmdsize(syssize);
}
UHYVE_PORT_CMDVAL => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let syscmdval =
unsafe { &*(self.host_address(data_addr) as *const SysCmdval) };
self.cmdval(syscmdval);
}
UHYVE_PORT_NETWRITE => {
match &self.tx {
Some(tx_channel) => tx_channel.send(1).unwrap(),

None => {}
};
}
UHYVE_PORT_EXIT => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let sysexit =
unsafe { &*(self.host_address(data_addr) as *const SysExit) };
return Ok(VcpuStopReason::Exit(self.exit(sysexit)));
}
UHYVE_PORT_OPEN => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let sysopen =
unsafe { &mut *(self.host_address(data_addr) as *mut SysOpen) };
self.open(sysopen);
}
UHYVE_PORT_WRITE => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let syswrite =
unsafe { &*(self.host_address(data_addr) as *const SysWrite) };
self.write(syswrite)?;
}
UHYVE_PORT_READ => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let sysread =
unsafe { &mut *(self.host_address(data_addr) as *mut SysRead) };
self.read(sysread);
}
UHYVE_PORT_UNLINK => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let sysunlink = unsafe {
&mut *(self.host_address(data_addr) as *mut SysUnlink)
};
self.unlink(sysunlink);
}
UHYVE_PORT_LSEEK => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let syslseek = unsafe {
&mut *(self.host_address(data_addr) as *mut SysLseek)
};
self.lseek(syslseek);
}
UHYVE_PORT_CLOSE => {
let data_addr: usize =
unsafe { (*(addr.as_ptr() as *const u32)) as usize };
let sysclose = unsafe {
&mut *(self.host_address(data_addr) as *mut SysClose)
};
self.close(sysclose);
}
//TODO:
PCI_CONFIG_DATA_PORT => {
if let Some(pci_addr) = self.pci_addr {
if pci_addr & 0x1ff800 == 0 {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.handle_write(pci_addr & 0x3ff, addr);
let data_addr: usize = unsafe { (*(addr.as_ptr() as *const u32)) as usize };
if let Some(hypercall) =
unsafe { self.address_to_hypercall(port, data_addr) }
{
match hypercall {
Hypercall::Cmdsize(syssize) => self.cmdsize(syssize),
Hypercall::Cmdval(syscmdval) => self.cmdval(syscmdval),
Hypercall::Exit(sysexit) => {
return Ok(VcpuStopReason::Exit(self.exit(sysexit)));
}
Hypercall::FileClose(sysclose) => self.close(sysclose),
Hypercall::FileLseek(syslseek) => self.lseek(syslseek),
Hypercall::FileOpen(sysopen) => self.open(sysopen),
Hypercall::FileRead(sysread) => self.read(sysread),
Hypercall::FileWrite(syswrite) => self.write(syswrite)?,
Hypercall::FileUnlink(sysunlink) => self.unlink(sysunlink),
Hypercall::SerialWriteByte(buf) => self.uart(&[buf])?,
_ => panic!("Got unknown hypercall {:?}", hypercall),
};
} else {
match port {
UHYVE_PORT_NETWRITE => {
match &self.tx {
Some(tx_channel) => tx_channel.send(1).unwrap(),
None => {}
};
}
//TODO:
PCI_CONFIG_DATA_PORT => {
if let Some(pci_addr) = self.pci_addr {
if pci_addr & 0x1ff800 == 0 {
let mut virtio_device =
self.virtio_device.lock().unwrap();
virtio_device.handle_write(pci_addr & 0x3ff, addr);
}
}
}
}
PCI_CONFIG_ADDRESS_PORT => {
self.pci_addr = Some(unsafe { *(addr.as_ptr() as *const u32) });
}
VIRTIO_PCI_STATUS => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_status(addr);
}
VIRTIO_PCI_GUEST_FEATURES => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_requested_features(addr);
}
VIRTIO_PCI_QUEUE_NOTIFY => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.handle_notify_output(addr, self);
}
VIRTIO_PCI_QUEUE_SEL => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_selected_queue(addr);
}
VIRTIO_PCI_QUEUE_PFN => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_pfn(addr, self);
}
_ => {
panic!("Unhandled IO exit: 0x{port:x}");
PCI_CONFIG_ADDRESS_PORT => {
self.pci_addr = Some(unsafe { *(addr.as_ptr() as *const u32) });
}
VIRTIO_PCI_STATUS => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_status(addr);
}
VIRTIO_PCI_GUEST_FEATURES => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_requested_features(addr);
}
VIRTIO_PCI_QUEUE_NOTIFY => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.handle_notify_output(addr, self);
}
VIRTIO_PCI_QUEUE_SEL => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_selected_queue(addr);
}
VIRTIO_PCI_QUEUE_PFN => {
let mut virtio_device = self.virtio_device.lock().unwrap();
virtio_device.write_pfn(addr, self);
}
_ => {
panic!("Unhandled IO exit: 0x{:x}", port);
}
}
}
}
Expand Down
44 changes: 27 additions & 17 deletions src/macos/aarch64/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{
};

use log::debug;
use uhyve_interface::Hypercall;
use xhypervisor::{self, Register, SystemRegister, VirtualCpuExitReason};

use crate::{
Expand All @@ -15,7 +16,7 @@ use crate::{
PSR, TCR_FLAGS, TCR_TG1_4K, VA_BITS,
},
consts::*,
vm::{HypervisorResult, SysExit, VcpuStopReason, VirtualCPU},
vm::{HypervisorResult, VcpuStopReason, VirtualCPU},
};

pub struct UhyveCPU {
Expand Down Expand Up @@ -176,24 +177,33 @@ impl VirtualCPU for UhyveCPU {
let addr: u16 = exception.physical_address.try_into().unwrap();
let pc = self.vcpu.read_register(Register::PC)?;

match addr {
UHYVE_UART_PORT => {
let x8 = (self.vcpu.read_register(Register::X8)? & 0xFF) as u8;
let data_addr = self.vcpu.read_register(Register::X8)?;
if let Some(hypercall) =
unsafe { self.address_to_hypercall(port, data_addr as usize) }
{
match hypercall {
Hypercall::SerialWriteByte(_char) => {
let x8 = (self.vcpu.read_register(Register::X8)? & 0xFF) as u8;

self.uart(&[x8]).unwrap();
self.vcpu.write_register(Register::PC, pc + 4)?;
self.uart(&[x8]).unwrap();
}
Hypercall::Exit(sysexit) => {
return Ok(VcpuStopReason::Exit(self.exit(sysexit)));
}
_ => {
panic! {"Hypercall {hypercall:?} not implemented on macos-aarch64"}
}
}
UHYVE_PORT_EXIT => {
let data_addr = self.vcpu.read_register(Register::X8)?;
let sysexit = unsafe {
&*(self.host_address(data_addr as usize) as *const SysExit)
};
return Ok(VcpuStopReason::Exit(self.exit(sysexit)));
}
_ => {
error!("Unable to handle exception {:?}", exception);
self.print_registers();
return Err(xhypervisor::Error::Error);
// increase the pc to the instruction after the exception to continue execution
self.vcpu.write_register(Register::PC, pc + 4)?;
} else {
#[allow(clippy::match_single_binding)]
match addr {
_ => {
error!("Unable to handle exception {:?}", exception);
self.print_registers();
return Err(xhypervisor::Error::Error);
}
}
}
} else {
Expand Down
Loading

0 comments on commit bc902db

Please sign in to comment.