summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatt Delco <delco@chromium.org>2020-02-25 18:01:05 -0800
committerCommit Bot <commit-bot@chromium.org>2020-03-05 19:01:24 +0000
commitd2a862b41f07d387926f0b984c56dc838003102c (patch)
treef7f03c7c31673efc0b29cc4bf74804f638dac172 /src
parentb9f4c9bca30e65eacfb055951fa994ad5127a8f0 (diff)
downloadcrosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar.gz
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar.bz2
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar.lz
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar.xz
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.tar.zst
crosvm-d2a862b41f07d387926f0b984c56dc838003102c.zip
crosvm: add handling for hyperv exits
When features for Hyper-V are enabled there's a another type of exit
that can be triggered.  This change attempts to add support for those
types of exits.

BUG=b:150151095
TEST=ran build_test

Change-Id: I3131a2c8d9c610576ac177dbfe82f78e8d5dbfb1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2073254
Reviewed-by: Matt Delco <delco@chromium.org>
Tested-by: Matt Delco <delco@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Matt Delco <delco@chromium.org>
Auto-Submit: Matt Delco <delco@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/plugin/mod.rs15
-rw-r--r--src/plugin/vcpu.rs48
2 files changed, 63 insertions, 0 deletions
diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs
index adda9a3..1c7027f 100644
--- a/src/plugin/mod.rs
+++ b/src/plugin/mod.rs
@@ -517,6 +517,21 @@ pub fn run_vcpus(
                                             &vcpu,
                                         );
                                     }
+                                    VcpuExit::HypervHcall { input, params } => {
+                                        let mut data = [0; 8];
+                                        vcpu_plugin.hyperv_call(input, params, &mut data, &vcpu);
+                                        // Setting data for hyperv call can not fail.
+                                        let _ = vcpu.set_data(&data);
+                                    }
+                                    VcpuExit::HypervSynic {
+                                        msr,
+                                        control,
+                                        evt_page,
+                                        msg_page,
+                                    } => {
+                                        vcpu_plugin
+                                            .hyperv_synic(msr, control, evt_page, msg_page, &vcpu);
+                                    }
                                     VcpuExit::Hlt => break,
                                     VcpuExit::Shutdown => break,
                                     VcpuExit::InternalError => {
diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs
index ae96789..3bb6bed 100644
--- a/src/plugin/vcpu.rs
+++ b/src/plugin/vcpu.rs
@@ -513,6 +513,54 @@ impl PluginVcpu {
         self.process(IoSpace::Mmio, addr, VcpuRunData::Write(data), vcpu)
     }
 
+    /// Has the plugin process handle a hyper-v call.
+    pub fn hyperv_call(&self, input: u64, params: [u64; 2], data: &mut [u8], vcpu: &Vcpu) -> bool {
+        let mut wait_reason = VcpuResponse_Wait::new();
+        let hv = wait_reason.mut_hyperv_call();
+        hv.input = input;
+        hv.params0 = params[0];
+        hv.params1 = params[1];
+
+        self.wait_reason.set(Some(wait_reason));
+        match self.handle_until_resume(vcpu) {
+            Ok(resume_data) => {
+                data.copy_from_slice(&resume_data);
+                true
+            }
+            Err(e) if e.errno() == EPIPE => false,
+            Err(e) => {
+                error!("failed to process hyperv call request: {}", e);
+                false
+            }
+        }
+    }
+
+    /// Has the plugin process handle a synic config change.
+    pub fn hyperv_synic(
+        &self,
+        msr: u32,
+        control: u64,
+        evt_page: u64,
+        msg_page: u64,
+        vcpu: &Vcpu,
+    ) -> bool {
+        let mut wait_reason = VcpuResponse_Wait::new();
+        let hv = wait_reason.mut_hyperv_synic();
+        hv.msr = msr;
+        hv.control = control;
+        hv.evt_page = evt_page;
+        hv.msg_page = msg_page;
+        self.wait_reason.set(Some(wait_reason));
+        match self.handle_until_resume(vcpu) {
+            Ok(_resume_data) => true,
+            Err(e) if e.errno() == EPIPE => false,
+            Err(e) => {
+                error!("failed to process hyperv synic request: {}", e);
+                false
+            }
+        }
+    }
+
     fn handle_request(&self, vcpu: &Vcpu) -> SysResult<Option<Vec<u8>>> {
         let mut wait_reason = self.wait_reason.take();
         let mut do_recv = true;