aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorjohannst <johannes.stoelp@gmail.com>2021-06-01 22:48:01 +0200
committerjohannst <johannes.stoelp@gmail.com>2021-06-01 22:48:01 +0200
commit387dd9e27b9425f23ff0eb0c6e9ea785a762fd48 (patch)
tree84f4ff979dd5232421431b8ba0f6c6cb9d7493f0
parentccc0081adc056b9a5df1b4b704d2e680ec979b2c (diff)
downloadmini-kvm-rs-387dd9e27b9425f23ff0eb0c6e9ea785a762fd48.tar.gz
mini-kvm-rs-387dd9e27b9425f23ff0eb0c6e9ea785a762fd48.zip
add support for IoIn / MmioRead exit
-rw-r--r--src/lib.rs10
-rw-r--r--src/vcpu.rs23
2 files changed, 21 insertions, 12 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 9690eaa..d31d33e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -126,7 +126,7 @@ impl KvmRun {
libc::mmap(
std::ptr::null_mut(),
len,
- libc::PROT_READ,
+ libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
vcpu.as_raw_fd(),
0,
@@ -153,6 +153,12 @@ impl ops::Drop for KvmRun {
impl AsRef<kvm_sys::kvm_run> for KvmRun {
fn as_ref(&self) -> &kvm_sys::kvm_run {
- unsafe { &(*self.ptr) }
+ unsafe { & *(self.ptr as *const kvm_sys::kvm_run) }
+ }
+}
+
+impl AsMut<kvm_sys::kvm_run> for KvmRun {
+ fn as_mut(&mut self) -> &mut kvm_sys::kvm_run {
+ unsafe { &mut *(self.ptr as *mut kvm_sys::kvm_run) }
}
}
diff --git a/src/vcpu.rs b/src/vcpu.rs
index 988bedc..085a3c7 100644
--- a/src/vcpu.rs
+++ b/src/vcpu.rs
@@ -5,7 +5,9 @@ use crate::{ioctl, kvm_sys, KvmRun};
pub enum KvmExit<'cpu> {
Halt,
+ IoIn(u16, &'cpu mut [u8]),
IoOut(u16, &'cpu [u8]),
+ MmioRead(u64, &'cpu mut [u8]),
MmioWrite(u64, &'cpu [u8]),
}
@@ -52,10 +54,10 @@ impl Vcpu {
.map(|_| ())
}
- pub fn run(&self) -> io::Result<KvmExit> {
+ pub fn run(&mut self) -> io::Result<KvmExit> {
ioctl(&self.vcpu, kvm_sys::KVM_RUN, 0)?;
- let kvm_run = self.kvm_run.as_ref();
+ let kvm_run = self.kvm_run.as_mut();
match kvm_run.exit_reason as u64 {
kvm_sys::KVM_EXIT_HLT => Ok(KvmExit::Halt),
@@ -63,31 +65,32 @@ impl Vcpu {
// Safe to use union `io` field, as Kernel instructed us to.
let io = unsafe { kvm_run.inner.io };
- let kvm_run_ptr = kvm_run as *const kvm_sys::kvm_run as *const u8;
+ let kvm_run_ptr = kvm_run as *mut kvm_sys::kvm_run as *mut u8;
// Create IO buffer located at `kvm_run + io.offset`.
let data = unsafe {
- std::slice::from_raw_parts(
+ std::slice::from_raw_parts_mut(
kvm_run_ptr.offset(io.data_offset as isize),
io.count /* num blocks */ as usize * io.size /* bytes per block */ as usize,
)
};
match io.direction as u64 {
- kvm_sys::KVM_EXIT_IO_IN => todo!("KVM_EXIT_IO_IN not implemented!"),
+ kvm_sys::KVM_EXIT_IO_IN => Ok(KvmExit::IoIn(io.port, data)),
kvm_sys::KVM_EXIT_IO_OUT => Ok(KvmExit::IoOut(io.port, data)),
_ => unreachable!(),
}
}
kvm_sys::KVM_EXIT_MMIO => {
// Safe to use union `mmio` filed, as Kernel instructed us to.
- let mmio = unsafe { &kvm_run.inner.mmio };
+ let mmio = unsafe { &mut kvm_run.inner.mmio };
let len = mmio.len as usize;
- // Only support write at the moment.
- assert_ne!(0, mmio.is_write);
-
- Ok(KvmExit::MmioWrite(mmio.phys_addr, &mmio.data[..len]))
+ match mmio.is_write {
+ 0 => Ok(KvmExit::MmioRead(mmio.phys_addr, &mut mmio.data[..len])),
+ 1 => Ok(KvmExit::MmioWrite(mmio.phys_addr, &mmio.data[..len])),
+ _ => unreachable!(),
+ }
}
r @ _ => {
todo!("KVM_EXIT_... (exit_reason={}) not implemented!", r)