hypervisor: x86: Add a SegmentRegistorOps trait

In order to validate emulated memory accesses, we need to be able to get
all the segments descriptor attributes.

This is done by abstracting the SegmentRegister attributes through a
trait that each hypervisor will have to implement.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2020-11-27 00:17:59 +01:00 committed by Rob Bradford
parent 3faffcb087
commit d419e30df1
2 changed files with 123 additions and 1 deletions

View File

@ -65,3 +65,60 @@ pub enum Exception {
}
pub mod regs;
// Abstracted segment register ops.
// Each x86 hypervisor should implement those.
pub trait SegmentRegisterOps {
// Segment type
fn segment_type(&self) -> u8;
fn set_segment_type(&mut self, val: u8);
// Descriptor Privilege Level (DPL)
fn dpl(&self) -> u8;
fn set_dpl(&mut self, val: u8);
// Granularity
fn granularity(&self) -> u8;
fn set_granularity(&mut self, val: u8);
// Memory Presence
fn present(&self) -> u8;
fn set_present(&mut self, val: u8);
// Long mode
fn long(&self) -> u8;
fn set_long(&mut self, val: u8);
// Available for system use (AVL)
fn avl(&self) -> u8;
fn set_avl(&mut self, val: u8);
// Descriptor type (System or code/data)
fn desc_type(&self) -> u8;
fn set_desc_type(&mut self, val: u8);
// D/B
fn db(&self) -> u8;
fn set_db(&mut self, val: u8);
}
// Code segment
pub const CODE_SEGMENT_TYPE: u8 = 0x8;
// Read/Write or Read/Exec segment
pub const RWRX_SEGMENT_TYPE: u8 = 0x2;
// Expand down segment
pub const EXPAND_DOWN_SEGMENT_TYPE: u8 = 0x4;
pub fn segment_type_code(t: u8) -> bool {
t & CODE_SEGMENT_TYPE != 0
}
pub fn segment_type_ro(t: u8) -> bool {
t & !RWRX_SEGMENT_TYPE == 0
}
pub fn segment_type_expand_down(t: u8) -> bool {
!segment_type_code(t) && (t & EXPAND_DOWN_SEGMENT_TYPE != 0)
}

View File

@ -10,7 +10,7 @@
use vm_memory::GuestAddress;
use crate::arch::x86::{msr_index, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
use serde_derive::{Deserialize, Serialize};
@ -28,6 +28,71 @@ pub use {
kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX as CPUID_FLAG_VALID_INDEX,
};
impl SegmentRegisterOps for SegmentRegister {
fn segment_type(&self) -> u8 {
self.type_
}
fn set_segment_type(&mut self, val: u8) {
self.type_ = val;
}
fn dpl(&self) -> u8 {
self.dpl
}
fn set_dpl(&mut self, val: u8) {
self.dpl = val;
}
fn present(&self) -> u8 {
self.present
}
fn set_present(&mut self, val: u8) {
self.present = val;
}
fn long(&self) -> u8 {
self.l
}
fn set_long(&mut self, val: u8) {
self.l = val;
}
fn avl(&self) -> u8 {
self.avl
}
fn set_avl(&mut self, val: u8) {
self.avl = val;
}
fn desc_type(&self) -> u8 {
self.s
}
fn set_desc_type(&mut self, val: u8) {
self.s = val;
}
fn granularity(&self) -> u8 {
self.g
}
fn set_granularity(&mut self, val: u8) {
self.g = val;
}
fn db(&self) -> u8 {
self.db
}
fn set_db(&mut self, val: u8) {
self.db = val;
}
}
pub const KVM_TSS_ADDRESS: GuestAddress = GuestAddress(0xfffb_d000);
macro_rules! msr {