forked from rcore-os/zCore
hypervisor: ensure the thread of vcpu has not been changed
This commit is contained in:
parent
4fea25a76e
commit
82ca3d891a
|
@ -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<Thread>,
|
||||
inner: Mutex<VcpuInner>,
|
||||
}
|
||||
|
||||
|
@ -20,15 +22,24 @@ impl_kobject!(Vcpu);
|
|||
define_count_helper!(Vcpu);
|
||||
|
||||
impl Vcpu {
|
||||
pub fn new(guest: Arc<Guest>, entry: u64) -> ZxResult<Arc<Self>> {
|
||||
// TODO: check thread
|
||||
pub fn new(guest: Arc<Guest>, entry: u64, thread: Arc<Thread>) -> ZxResult<Arc<Self>> {
|
||||
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<Thread>) -> 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<PortPacket> {
|
||||
// TODO: check thread
|
||||
self.inner.lock().resume()?.try_into()
|
||||
}
|
||||
|
||||
pub fn read_state(&self) -> ZxResult<VcpuState> {
|
||||
// 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<rvm::BellPacket> for PacketGuestBell {
|
||||
fn from(bell: rvm::BellPacket) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -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<Process>, name: &str, _options: u32) -> ZxResult<Arc<Self>> {
|
||||
|
@ -389,6 +398,17 @@ impl Thread {
|
|||
}
|
||||
ExceptionFuture
|
||||
}
|
||||
|
||||
pub fn get_flags(&self) -> ThreadFlag {
|
||||
self.inner.lock().flags
|
||||
}
|
||||
|
||||
pub fn update_flags<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut ThreadFlag),
|
||||
{
|
||||
f(&mut self.inner.lock().flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl Task for Thread {
|
||||
|
|
|
@ -91,7 +91,7 @@ impl Syscall<'_> {
|
|||
}
|
||||
let proc = self.thread.proc();
|
||||
let guest = proc.get_object_with_rights::<Guest>(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::<Vcpu>(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::<Vcpu>(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::<Vcpu>(handle, Rights::WRITE)?;
|
||||
if !vcpu.same_thread(&self.thread) {
|
||||
return Err(ZxError::BAD_STATE);
|
||||
}
|
||||
|
||||
match VcpuReadWriteKind::try_from(kind) {
|
||||
Ok(VcpuReadWriteKind::VcpuState) => {
|
||||
|
|
Loading…
Reference in New Issue