hypervisor: x86: provide a generic SegmentRegister structure

And drop SegmentRegisterOps since it is no longer required.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu
2022-07-14 21:36:08 +00:00
committed by Liu Wei
parent 8b7781e267
commit 75797827d5
8 changed files with 191 additions and 197 deletions

View File

@@ -8,9 +8,9 @@ use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, P
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::{CR0_PE, EFER_LMA};
use crate::arch::x86::{
segment_type_expand_down, segment_type_ro, Exception, SegmentRegisterOps, StandardRegisters,
segment_type_expand_down, segment_type_ro, Exception, SegmentRegister, StandardRegisters,
};
use crate::x86_64::{SegmentRegister, SpecialRegisters};
use crate::x86_64::SpecialRegisters;
use anyhow::Context;
use iced_x86::*;
@@ -390,12 +390,12 @@ impl CpuStateManager for EmulatorCpuState {
}
match reg {
Register::CS => Ok(self.sregs.cs),
Register::DS => Ok(self.sregs.ds),
Register::ES => Ok(self.sregs.es),
Register::FS => Ok(self.sregs.fs),
Register::GS => Ok(self.sregs.gs),
Register::SS => Ok(self.sregs.ss),
Register::CS => Ok(self.sregs.cs.into()),
Register::DS => Ok(self.sregs.ds.into()),
Register::ES => Ok(self.sregs.es.into()),
Register::FS => Ok(self.sregs.fs.into()),
Register::GS => Ok(self.sregs.gs.into()),
Register::SS => Ok(self.sregs.ss.into()),
r => Err(PlatformError::InvalidRegister(anyhow!(
"read_segment invalid register {:?}",
r
@@ -413,12 +413,12 @@ impl CpuStateManager for EmulatorCpuState {
}
match reg {
Register::CS => self.sregs.cs = segment_register,
Register::DS => self.sregs.ds = segment_register,
Register::ES => self.sregs.es = segment_register,
Register::FS => self.sregs.fs = segment_register,
Register::GS => self.sregs.gs = segment_register,
Register::SS => self.sregs.ss = segment_register,
Register::CS => self.sregs.cs = segment_register.into(),
Register::DS => self.sregs.ds = segment_register.into(),
Register::ES => self.sregs.es = segment_register.into(),
Register::FS => self.sregs.fs = segment_register.into(),
Register::GS => self.sregs.gs = segment_register.into(),
Register::SS => self.sregs.ss = segment_register.into(),
r => return Err(PlatformError::InvalidRegister(anyhow!("{:?}", r))),
}

View File

@@ -8,7 +8,7 @@
// found in the LICENSE-BSD-3-Clause file.
// For GDT details see arch/x86/include/asm/segment.h
use crate::x86_64::SegmentRegister;
use crate::arch::x86::SegmentRegister;
/// Constructor for a conventional segment GDT (or LDT) entry. Derived from the kernel's segment.h.
pub fn gdt_entry(flags: u16, base: u32, limit: u32) -> u64 {
@@ -106,7 +106,6 @@ pub fn segment_from_gdt(entry: u64, table_index: u8) -> SegmentRegister {
l: get_l(entry),
g: get_g(entry),
avl: get_avl(entry),
padding: 0,
unusable: match get_p(entry) {
0 => 1,
_ => 0,

View File

@@ -53,40 +53,86 @@ 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);
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct SegmentRegister {
pub base: u64,
pub limit: u32,
pub selector: u16,
pub type_: u8,
pub present: u8,
pub dpl: u8,
pub db: u8,
pub s: u8,
pub l: u8,
pub g: u8,
pub avl: u8,
pub unusable: u8,
}
// Descriptor Privilege Level (DPL)
fn dpl(&self) -> u8;
fn set_dpl(&mut self, val: u8);
impl SegmentRegister {
pub fn segment_type(&self) -> u8 {
self.type_
}
pub fn set_segment_type(&mut self, val: u8) {
self.type_ = val;
}
// Granularity
fn granularity(&self) -> u8;
fn set_granularity(&mut self, val: u8);
pub fn dpl(&self) -> u8 {
self.dpl
}
// Memory Presence
fn present(&self) -> u8;
fn set_present(&mut self, val: u8);
pub fn set_dpl(&mut self, val: u8) {
self.dpl = val;
}
// Long mode
fn long(&self) -> u8;
fn set_long(&mut self, val: u8);
pub fn present(&self) -> u8 {
self.present
}
// Available for system use (AVL)
fn avl(&self) -> u8;
fn set_avl(&mut self, val: u8);
pub fn set_present(&mut self, val: u8) {
self.present = val;
}
// Descriptor type (System or code/data)
fn desc_type(&self) -> u8;
fn set_desc_type(&mut self, val: u8);
pub fn long(&self) -> u8 {
self.l
}
// D/B
fn db(&self) -> u8;
fn set_db(&mut self, val: u8);
pub fn set_long(&mut self, val: u8) {
self.l = val;
}
pub fn avl(&self) -> u8 {
self.avl
}
pub fn set_avl(&mut self, val: u8) {
self.avl = val;
}
pub fn desc_type(&self) -> u8 {
self.s
}
pub fn set_desc_type(&mut self, val: u8) {
self.s = val;
}
pub fn granularity(&self) -> u8 {
self.g
}
pub fn set_granularity(&mut self, val: u8) {
self.g = val;
}
pub fn db(&self) -> u8 {
self.db
}
pub fn set_db(&mut self, val: u8) {
self.db = val;
}
}
// Code segment