diff --git a/zircon-object/src/hypervisor/vcpu.rs b/zircon-object/src/hypervisor/vcpu.rs index f720e959..89336294 100644 --- a/zircon-object/src/hypervisor/vcpu.rs +++ b/zircon-object/src/hypervisor/vcpu.rs @@ -3,6 +3,7 @@ use { hypervisor::{Guest, VcpuIo, VcpuState}, object::*, signal::*, + task::{Thread, ThreadFlag}, }, alloc::sync::Arc, core::convert::TryInto, @@ -13,6 +14,7 @@ use { pub struct Vcpu { base: KObjectBase, _counter: CountHelper, + thread: Arc, inner: Mutex, } @@ -20,15 +22,24 @@ impl_kobject!(Vcpu); define_count_helper!(Vcpu); impl Vcpu { - pub fn new(guest: Arc, entry: u64) -> ZxResult> { - // TODO: check thread + pub fn new(guest: Arc, entry: u64, thread: Arc) -> ZxResult> { + if thread.get_flags().contains(ThreadFlag::VCPU) { + return Err(ZxError::BAD_STATE); + } + let inner = Mutex::new(VcpuInner::new(entry, guest.rvm_geust())?); + thread.update_flags(|flags| flags.insert(ThreadFlag::VCPU)); Ok(Arc::new(Vcpu { base: KObjectBase::new(), _counter: CountHelper::new(), - inner: Mutex::new(VcpuInner::new(entry, guest.rvm_geust())?), + thread, + inner, })) } + pub fn same_thread(&self, current_thread: &Arc) -> bool { + Arc::ptr_eq(&self.thread, current_thread) + } + pub fn virtual_interrupt(&self, vector: u32) -> ZxResult { self.inner .lock() @@ -37,26 +48,29 @@ impl Vcpu { } pub fn resume(&self) -> ZxResult { - // TODO: check thread self.inner.lock().resume()?.try_into() } pub fn read_state(&self) -> ZxResult { - // TODO: check thread self.inner.lock().read_state().map_err(From::from) } pub fn write_state(&self, state: &VcpuState) -> ZxResult { - // TODO: check thread self.inner.lock().write_state(state).map_err(From::from) } pub fn write_io_state(&self, state: &VcpuIo) -> ZxResult { - // TODO: check thread self.inner.lock().write_io_state(state).map_err(From::from) } } +impl Drop for Vcpu { + fn drop(&mut self) { + self.thread + .update_flags(|flags| flags.remove(ThreadFlag::VCPU)); + } +} + impl From for PacketGuestBell { fn from(bell: rvm::BellPacket) -> Self { Self { diff --git a/zircon-object/src/task/thread.rs b/zircon-object/src/task/thread.rs index 04407e98..710d441d 100644 --- a/zircon-object/src/task/thread.rs +++ b/zircon-object/src/task/thread.rs @@ -4,6 +4,7 @@ use { super::*, crate::object::*, alloc::{boxed::Box, sync::Arc}, + bitflags::bitflags, core::{ any::Any, future::Future, @@ -120,6 +121,7 @@ struct ThreadInner { state: ThreadState, /// The time this thread has run on cpu time: u128, + flags: ThreadFlag, } impl ThreadInner { @@ -132,6 +134,13 @@ impl ThreadInner { } } +bitflags! { + #[derive(Default)] + pub struct ThreadFlag: usize { + const VCPU = 1 << 3; + } +} + impl Thread { /// Create a new thread. pub fn create(proc: &Arc, name: &str, _options: u32) -> ZxResult> { @@ -389,6 +398,17 @@ impl Thread { } ExceptionFuture } + + pub fn get_flags(&self) -> ThreadFlag { + self.inner.lock().flags + } + + pub fn update_flags(&self, f: F) + where + F: FnOnce(&mut ThreadFlag), + { + f(&mut self.inner.lock().flags) + } } impl Task for Thread { diff --git a/zircon-syscall/src/hypervisor.rs b/zircon-syscall/src/hypervisor.rs index 4d8339a3..88a88274 100644 --- a/zircon-syscall/src/hypervisor.rs +++ b/zircon-syscall/src/hypervisor.rs @@ -91,7 +91,7 @@ impl Syscall<'_> { } let proc = self.thread.proc(); let guest = proc.get_object_with_rights::(guest_handle, Rights::MANAGE_PROCESS)?; - let vcpu = Vcpu::new(guest, entry)?; + let vcpu = Vcpu::new(guest, entry, self.thread.clone())?; let handle_value = proc.add_handle(Handle::new(vcpu, Rights::DEFAULT_VCPU)); out.write(handle_value)?; Ok(()) @@ -105,6 +105,9 @@ impl Syscall<'_> { info!("hypervisor.vcpu_resume: handle={:#x?}", handle); let proc = self.thread.proc(); let vcpu = proc.get_object_with_rights::(handle, Rights::EXECUTE)?; + if !vcpu.same_thread(&self.thread) { + return Err(ZxError::BAD_STATE); + } let packet = vcpu.resume()?; user_packet.write(packet)?; Ok(()) @@ -137,6 +140,9 @@ impl Syscall<'_> { } let proc = self.thread.proc(); let vcpu = proc.get_object_with_rights::(handle, Rights::READ)?; + if !vcpu.same_thread(&self.thread) { + return Err(ZxError::BAD_STATE); + } let state = vcpu.read_state()?; user_buffer.write(state)?; Ok(()) @@ -155,6 +161,9 @@ impl Syscall<'_> { ); let proc = self.thread.proc(); let vcpu = proc.get_object_with_rights::(handle, Rights::WRITE)?; + if !vcpu.same_thread(&self.thread) { + return Err(ZxError::BAD_STATE); + } match VcpuReadWriteKind::try_from(kind) { Ok(VcpuReadWriteKind::VcpuState) => {