mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
hypervisor: x86_64: add Default impl for Sregs
Replace the Sregs Default implementation with one that provides the register values at reset, based on the Intel software developer manual. The x86_64 tests need to be adjusted to only check the CR0 bits they intend to match, since the default Sregs value now includes other set bits. BUG=b:237095693 TEST=Boot x86-64 Linux kernel TEST=cargo test -p x86_64 Change-Id: If966941df43225572e79ebd9213671348e2846f4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3735640 Reviewed-by: Alexandre Courbot <acourbot@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
6f576dd813
commit
91a4b090da
2 changed files with 100 additions and 3 deletions
|
@ -630,7 +630,7 @@ pub struct DescriptorTable {
|
|||
|
||||
/// State of a VCPU's special registers.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Sregs {
|
||||
pub cs: Segment,
|
||||
pub ds: Segment,
|
||||
|
@ -655,6 +655,103 @@ pub struct Sregs {
|
|||
pub interrupt_bitmap: [u64; 4usize],
|
||||
}
|
||||
|
||||
impl Default for Sregs {
|
||||
fn default() -> Self {
|
||||
// Intel SDM Vol. 3A, 3.4.5.1 ("Code- and Data-Segment Descriptor Types")
|
||||
const SEG_TYPE_DATA: u8 = 0b0000;
|
||||
const SEG_TYPE_DATA_WRITABLE: u8 = 0b0010;
|
||||
|
||||
const SEG_TYPE_CODE: u8 = 0b1000;
|
||||
const SEG_TYPE_CODE_READABLE: u8 = 0b0010;
|
||||
|
||||
const SEG_TYPE_ACCESSED: u8 = 0b0001;
|
||||
|
||||
// Intel SDM Vol. 3A, 3.4.5 ("Segment Descriptors")
|
||||
const SEG_S_SYSTEM: u8 = 0; // System segment.
|
||||
const SEG_S_CODE_OR_DATA: u8 = 1; // Data/code segment.
|
||||
|
||||
// 16-bit real-mode code segment (reset vector).
|
||||
let code_seg = Segment {
|
||||
base: 0xffff0000,
|
||||
limit: 0xffff,
|
||||
selector: 0xf000,
|
||||
type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
|
||||
present: 1,
|
||||
s: SEG_S_CODE_OR_DATA,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// 16-bit real-mode data segment.
|
||||
let data_seg = Segment {
|
||||
base: 0,
|
||||
limit: 0xffff,
|
||||
selector: 0,
|
||||
type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE | SEG_TYPE_ACCESSED, // 3
|
||||
present: 1,
|
||||
s: SEG_S_CODE_OR_DATA,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// 16-bit TSS segment.
|
||||
let task_seg = Segment {
|
||||
base: 0,
|
||||
limit: 0xffff,
|
||||
selector: 0,
|
||||
type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
|
||||
present: 1,
|
||||
s: SEG_S_SYSTEM,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Local descriptor table.
|
||||
let ldt = Segment {
|
||||
base: 0,
|
||||
limit: 0xffff,
|
||||
selector: 0,
|
||||
type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE, // 2
|
||||
present: 1,
|
||||
s: SEG_S_SYSTEM,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Global descriptor table.
|
||||
let gdt = DescriptorTable {
|
||||
base: 0,
|
||||
limit: 0xffff,
|
||||
};
|
||||
|
||||
// Interrupt descriptor table.
|
||||
let idt = DescriptorTable {
|
||||
base: 0,
|
||||
limit: 0xffff,
|
||||
};
|
||||
|
||||
let cr0 = (1 << 4) // CR0.ET (reserved, always 1)
|
||||
| (1 << 30); // CR0.CD (cache disable)
|
||||
|
||||
Sregs {
|
||||
cs: code_seg,
|
||||
ds: data_seg,
|
||||
es: data_seg,
|
||||
fs: data_seg,
|
||||
gs: data_seg,
|
||||
ss: data_seg,
|
||||
tr: task_seg,
|
||||
ldt,
|
||||
gdt,
|
||||
idt,
|
||||
cr0,
|
||||
cr2: 0,
|
||||
cr3: 0,
|
||||
cr4: 0,
|
||||
cr8: 0,
|
||||
efer: 0,
|
||||
apic_base: 0,
|
||||
interrupt_bitmap: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State of a VCPU's floating point unit.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
|
|
@ -381,7 +381,7 @@ mod tests {
|
|||
assert_eq!(0, sregs.tr.base);
|
||||
assert_eq!(0xfffff, sregs.tr.limit);
|
||||
assert_eq!(0, sregs.tr.avl);
|
||||
assert_eq!(X86_CR0_PE, sregs.cr0);
|
||||
assert_eq!(X86_CR0_PE, sregs.cr0 & X86_CR0_PE);
|
||||
assert_eq!(EFER_LME, sregs.efer);
|
||||
}
|
||||
|
||||
|
@ -399,6 +399,6 @@ mod tests {
|
|||
|
||||
assert_eq!(0x9000, sregs.cr3);
|
||||
assert_eq!(X86_CR4_PAE, sregs.cr4);
|
||||
assert_eq!(X86_CR0_PG, sregs.cr0);
|
||||
assert_eq!(X86_CR0_PG, sregs.cr0 & X86_CR0_PG);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue