mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-27 02:28:22 +00:00
x86_64: Add x86_64 setup code
Change-Id: Ibdf83f8efcc92bf1f45ed9a5f95117fd9ae3ad5a Reviewed-on: https://chromium-review.googlesource.com/483868 Commit-Ready: Dylan Reid <dgreid@chromium.org> Tested-by: Dylan Reid <dgreid@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
abd3707450
commit
67030be903
8 changed files with 1341 additions and 1 deletions
11
x86_64/Cargo.toml
Normal file
11
x86_64/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "x86_64"
|
||||
version = "0.1.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
|
||||
[dependencies]
|
||||
kvm_sys = { path = "../kvm_sys" }
|
||||
kvm = { path = "../kvm" }
|
||||
sys_util = { path = "../sys_util" }
|
||||
libc = "*"
|
||||
byteorder = "*"
|
|
@ -1,4 +1,12 @@
|
|||
/* automatically generated by rust-bindgen */
|
||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* automatically generated by rust-bindgen
|
||||
* From upstream linux bootparam.h at commit:
|
||||
* 806276b7f07a39a1cc3f38bb1ef5c573d4594a38
|
||||
*/
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
|
|
114
x86_64/src/cpuid.rs
Normal file
114
x86_64/src/cpuid.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::result;
|
||||
|
||||
use kvm;
|
||||
use sys_util;
|
||||
|
||||
const MAX_KVM_CPUID_ENTRIES: usize = 256;
|
||||
const VENDOR_EBX_VAL: u32 = 0x534f5243;
|
||||
const VENDOR_ECX_VAL: u32 = 0x4d56534f;
|
||||
const VENDOR_EDX_VAL: u32 = 0x52434d56;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
GetSupportedCpusFailed(sys_util::Error),
|
||||
SetSupportedCpusFailed(sys_util::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
// CPUID bits in ebx, ecx, and edx.
|
||||
const EBX_CLFLUSH_CACHELINE: u32 = 8; // Flush a cache line size.
|
||||
const EBX_CLFLUSH_SIZE_SHIFT: u32 = 8; // Bytes flushed when executing CLFLUSH.
|
||||
const EBX_CPU_COUNT_SHIFT: u32 = 16; // Index of this CPU.
|
||||
const EBX_CPUID_SHIFT: u32 = 24; // Index of this CPU.
|
||||
const ECX_EPB_SHIFT: u32 = 3; // "Energy Performance Bias" bit.
|
||||
const ECX_HYPERVISOR_SHIFT: u32 = 31; // Flag to be set when the cpu is running on a hypervisor.
|
||||
const EDX_HTT_SHIFT: u32 = 28; // Hyper Threading Enabled.
|
||||
|
||||
fn filter_cpuid(cpu_id: u64, cpu_count: u64, kvm_cpuid: &mut kvm::CpuId) -> Result<()> {
|
||||
let entries = kvm_cpuid.mut_entries_slice();
|
||||
|
||||
for entry in entries.iter_mut() {
|
||||
match entry.function {
|
||||
0 => {
|
||||
// Vendor name "CROSVMCROSVM" in little endian.
|
||||
entry.ebx = VENDOR_EBX_VAL;
|
||||
entry.ecx = VENDOR_ECX_VAL;
|
||||
entry.edx = VENDOR_EDX_VAL;
|
||||
}
|
||||
1 => {
|
||||
// X86 hypervisor feature
|
||||
if entry.index == 0 {
|
||||
entry.ecx |= 1 << ECX_HYPERVISOR_SHIFT;
|
||||
}
|
||||
entry.ebx = (cpu_id << EBX_CPUID_SHIFT) as u32 |
|
||||
(EBX_CLFLUSH_CACHELINE << EBX_CLFLUSH_SIZE_SHIFT);
|
||||
if cpu_count > 1 {
|
||||
entry.ebx |= (cpu_count as u32) << EBX_CPU_COUNT_SHIFT;
|
||||
entry.edx |= 1 << EDX_HTT_SHIFT;
|
||||
}
|
||||
}
|
||||
6 => {
|
||||
// Clear X86 EPB feature. No frequency selection in the hypervisor.
|
||||
entry.ecx &= !(1 << ECX_EPB_SHIFT);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets up the cpuid entries for the given vcpu. Can fail if there are too many CPUs specified or
|
||||
/// if an ioctl returns an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `kvm` - `Kvm` structure created with KVM_CREATE_VM ioctl.
|
||||
/// * `vcpu` - `Vcpu` for setting CPU ID.
|
||||
/// * `cpu_id` - The index of the CPU `vcpu` is for.
|
||||
/// * `nrcpus` - The number of vcpus being used by this VM.
|
||||
pub fn setup_cpuid(kvm: &kvm::Kvm, vcpu: &kvm::Vcpu, cpu_id: u64, nrcpus: u64) -> Result<()> {
|
||||
let mut kvm_cpuid = kvm.get_supported_cpuid(MAX_KVM_CPUID_ENTRIES)
|
||||
.map_err(|e| Error::GetSupportedCpusFailed(e))?;
|
||||
|
||||
filter_cpuid(cpu_id, nrcpus, &mut kvm_cpuid)?;
|
||||
|
||||
vcpu.set_cpuid2(&kvm_cpuid)
|
||||
.map_err(|e| Error::SetSupportedCpusFailed(e))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn feature_and_vendor_name() {
|
||||
let mut cpuid = kvm::CpuId::new(2);
|
||||
|
||||
{
|
||||
let entries = cpuid.mut_entries_slice();
|
||||
entries[0].function = 0;
|
||||
entries[1].function = 1;
|
||||
entries[1].ecx = 0x10;
|
||||
entries[1].edx = 0;
|
||||
}
|
||||
assert_eq!(Ok(()), filter_cpuid(1, 2, &mut cpuid));
|
||||
{
|
||||
let entries = cpuid.mut_entries_slice();
|
||||
assert_eq!(entries[0].function, 0);
|
||||
assert_eq!(entries[0].ebx, VENDOR_EBX_VAL);
|
||||
assert_eq!(entries[0].ecx, VENDOR_ECX_VAL);
|
||||
assert_eq!(entries[0].edx, VENDOR_EDX_VAL);
|
||||
assert_eq!(1, (entries[1].ebx >> EBX_CPUID_SHIFT) & 0x000000ff);
|
||||
assert_eq!(2, (entries[1].ebx >> EBX_CPU_COUNT_SHIFT) & 0x000000ff);
|
||||
assert_eq!(EBX_CLFLUSH_CACHELINE,
|
||||
(entries[1].ebx >> EBX_CLFLUSH_SIZE_SHIFT) & 0x000000ff);
|
||||
assert_ne!(0, entries[1].ecx & (1 << ECX_HYPERVISOR_SHIFT));
|
||||
assert_ne!(0, entries[1].edx & (1 << EDX_HTT_SHIFT));
|
||||
}
|
||||
}
|
||||
}
|
109
x86_64/src/gdt.rs
Normal file
109
x86_64/src/gdt.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// For GDT details see arch/x86/include/asm/segment.h
|
||||
|
||||
use kvm_sys::kvm_segment;
|
||||
|
||||
/// 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 {
|
||||
((((base as u64) & 0xff000000u64) << (56 - 24)) | (((flags as u64) & 0x0000f0ffu64) << 40) |
|
||||
(((limit as u64) & 0x000f0000u64) << (48 - 16)) |
|
||||
(((base as u64) & 0x00ffffffu64) << 16) | (((limit as u64) & 0x0000ffffu64)))
|
||||
}
|
||||
|
||||
fn get_base(entry: u64) -> u64 {
|
||||
((((entry) & 0xFF00000000000000) >> 32) | (((entry) & 0x000000FF00000000) >> 16) |
|
||||
(((entry) & 0x00000000FFFF0000) >> 16))
|
||||
}
|
||||
|
||||
fn get_limit(entry: u64) -> u32 {
|
||||
((((entry) & 0x000F000000000000) >> 32) | (((entry) & 0x000000000000FFFF))) as u32
|
||||
}
|
||||
|
||||
fn get_g(entry: u64) -> u8 {
|
||||
((entry & 0x0080000000000000) >> 55) as u8
|
||||
}
|
||||
|
||||
fn get_db(entry: u64) -> u8 {
|
||||
((entry & 0x0040000000000000) >> 54) as u8
|
||||
}
|
||||
|
||||
fn get_l(entry: u64) -> u8 {
|
||||
((entry & 0x0020000000000000) >> 53) as u8
|
||||
}
|
||||
|
||||
fn get_avl(entry: u64) -> u8 {
|
||||
((entry & 0x0010000000000000) >> 52) as u8
|
||||
}
|
||||
|
||||
fn get_p(entry: u64) -> u8 {
|
||||
((entry & 0x0000800000000000) >> 47) as u8
|
||||
}
|
||||
|
||||
fn get_dpl(entry: u64) -> u8 {
|
||||
((entry & 0x0000600000000000) >> 45) as u8
|
||||
}
|
||||
|
||||
fn get_s(entry: u64) -> u8 {
|
||||
((entry & 0x0000100000000000) >> 44) as u8
|
||||
}
|
||||
|
||||
fn get_type(entry: u64) -> u8 {
|
||||
((entry & 0x00000F0000000000) >> 40) as u8
|
||||
}
|
||||
|
||||
/// Automatically build the kvm struct for SET_SREGS from the kernel bit fields.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `entry` - The gdt entry.
|
||||
/// * `table_index` - Index of the entry in the gdt table.
|
||||
pub fn kvm_segment_from_gdt(entry: u64, table_index: u8) -> kvm_segment {
|
||||
kvm_segment {
|
||||
base: get_base(entry),
|
||||
limit: get_limit(entry),
|
||||
selector: (table_index * 8) as u16,
|
||||
type_: get_type(entry),
|
||||
present: get_p(entry),
|
||||
dpl: get_dpl(entry),
|
||||
db: get_db(entry),
|
||||
s: get_s(entry),
|
||||
l: get_l(entry),
|
||||
g: get_g(entry),
|
||||
avl: get_avl(entry),
|
||||
padding: 0,
|
||||
unusable: match get_p(entry) {
|
||||
0 => 1,
|
||||
_ => 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn field_parse() {
|
||||
let gdt = gdt_entry(0xA09B, 0x100000, 0xfffff);
|
||||
let seg = kvm_segment_from_gdt(gdt, 0);
|
||||
// 0xA09B
|
||||
// 'A'
|
||||
assert_eq!(0x1, seg.g);
|
||||
assert_eq!(0x0, seg.db);
|
||||
assert_eq!(0x1, seg.l);
|
||||
assert_eq!(0x0, seg.avl);
|
||||
// '9'
|
||||
assert_eq!(0x1, seg.present);
|
||||
assert_eq!(0x0, seg.dpl);
|
||||
assert_eq!(0x1, seg.s);
|
||||
// 'B'
|
||||
assert_eq!(0xB, seg.type_);
|
||||
// base and limit
|
||||
assert_eq!(0x100000, seg.base);
|
||||
assert_eq!(0xfffff, seg.limit);
|
||||
assert_eq!(0x0, seg.unusable);
|
||||
}
|
||||
}
|
71
x86_64/src/interrupts.rs
Normal file
71
x86_64/src/interrupts.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::io::Cursor;
|
||||
use std::mem;
|
||||
use std::result;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use kvm;
|
||||
use kvm_sys::kvm_lapic_state;
|
||||
use sys_util;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
GetLapic(sys_util::Error),
|
||||
SetLapic(sys_util::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
// Defines poached from apicdef.h kernel header.
|
||||
const APIC_LVT0: usize = 0x350;
|
||||
const APIC_LVT1: usize = 0x360;
|
||||
const APIC_MODE_NMI: u32 = 0x4;
|
||||
const APIC_MODE_EXTINT: u32 = 0x7;
|
||||
|
||||
fn get_klapic_reg(klapic: &kvm_lapic_state, reg_offset: usize) -> u32 {
|
||||
let sliceu8 = unsafe {
|
||||
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
|
||||
// Cursors are only readable on arrays of u8, not i8(c_char).
|
||||
mem::transmute::<&[i8], &[u8]>(&klapic.regs[reg_offset..])
|
||||
};
|
||||
let mut reader = Cursor::new(sliceu8);
|
||||
// read_u32 can't fail if the offsets defined above are correct.
|
||||
reader.read_u32::<LittleEndian>().unwrap()
|
||||
}
|
||||
|
||||
fn set_klapic_reg(klapic: &mut kvm_lapic_state, reg_offset: usize, value: u32) {
|
||||
let sliceu8 = unsafe {
|
||||
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
|
||||
// Cursors are only readable on arrays of u8, not i8(c_char).
|
||||
mem::transmute::<&mut [i8], &mut [u8]>(&mut klapic.regs[reg_offset..])
|
||||
};
|
||||
let mut writer = Cursor::new(sliceu8);
|
||||
// read_u32 can't fail if the offsets defined above are correct.
|
||||
writer.write_u32::<LittleEndian>(value).unwrap()
|
||||
}
|
||||
|
||||
fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
|
||||
(((reg) & !0x700) | ((mode) << 8))
|
||||
}
|
||||
|
||||
/// Configures LAPICs. LAPIC0 is set for external interrupts, LAPIC1 is set for NMI.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `vcpu` - The VCPU object to configure.
|
||||
pub fn set_lint(vcpu: &kvm::Vcpu) -> Result<()> {
|
||||
let mut klapic = vcpu.get_lapic().map_err(|e| Error::GetLapic(e))?;
|
||||
|
||||
let lvt_lint0 = get_klapic_reg(&klapic, APIC_LVT0);
|
||||
set_klapic_reg(&mut klapic,
|
||||
APIC_LVT0,
|
||||
set_apic_delivery_mode(lvt_lint0, APIC_MODE_EXTINT));
|
||||
let lvt_lint1 = get_klapic_reg(&klapic, APIC_LVT1);
|
||||
set_klapic_reg(&mut klapic,
|
||||
APIC_LVT1,
|
||||
set_apic_delivery_mode(lvt_lint1, APIC_MODE_NMI));
|
||||
|
||||
vcpu.set_lapic(&klapic).map_err(|e| Error::SetLapic(e))
|
||||
}
|
166
x86_64/src/lib.rs
Normal file
166
x86_64/src/lib.rs
Normal file
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate kvm;
|
||||
extern crate kvm_sys;
|
||||
extern crate libc;
|
||||
extern crate sys_util;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case)]
|
||||
mod bootparam;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod msr_index;
|
||||
|
||||
mod cpuid;
|
||||
mod gdt;
|
||||
mod interrupts;
|
||||
mod regs;
|
||||
|
||||
use std::io::Write;
|
||||
use std::mem;
|
||||
use std::result;
|
||||
|
||||
use bootparam::boot_params;
|
||||
use bootparam::E820_RAM;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Error configuring the VCPU.
|
||||
CpuSetup(cpuid::Error),
|
||||
/// Error configuring the VCPU registers.
|
||||
RegisterConfiguration(regs::Error),
|
||||
/// Error configuring the VCPU floating point registers.
|
||||
FpuRegisterConfiguration(regs::Error),
|
||||
/// Error configuring the VCPU segment registers.
|
||||
SegmentRegisterConfiguration(regs::Error),
|
||||
/// Error configuring the VCPU local interrupt.
|
||||
LocalIntConfiguration(interrupts::Error),
|
||||
/// Error writing the zero page of guest memory.
|
||||
ZeroPageSetup,
|
||||
/// The zero page extends past the end of guest_mem.
|
||||
ZeroPagePastRamEnd,
|
||||
/// Invalid e820 setup params.
|
||||
E820Configuration,
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
const ZERO_PAGE_OFFSET: usize = 0x7000;
|
||||
const BOOT_STACK_POINTER: usize = 0x8000;
|
||||
const KERNEL_64BIT_ENTRY_OFFSET: usize = 0x200;
|
||||
|
||||
/// Configures the vcpu and should be called once per vcpu from the vcpu's thread.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `guest_mem` - The memory to be used by the guest.
|
||||
/// * `kernel_load_offset` - Offset from `guest_mem` at which the kernel starts.
|
||||
/// * `kvm` - The /dev/kvm object that created vcpu.
|
||||
/// * `vcpu` - The VCPU object to configure.
|
||||
/// * `num_cpus` - The number of vcpus that will be given to the guest.
|
||||
pub fn configure_vcpu(guest_mem: &mut [u8],
|
||||
kernel_load_offset: usize,
|
||||
kvm: &kvm::Kvm,
|
||||
vcpu: &kvm::Vcpu,
|
||||
num_cpus: usize)
|
||||
-> Result<()> {
|
||||
cpuid::setup_cpuid(&kvm, &vcpu, 0, num_cpus as u64).map_err(|e| Error::CpuSetup(e))?;
|
||||
regs::setup_msrs(&vcpu).map_err(|e| Error::RegisterConfiguration(e))?;
|
||||
regs::setup_regs(&vcpu, (kernel_load_offset + KERNEL_64BIT_ENTRY_OFFSET) as u64, BOOT_STACK_POINTER as u64, ZERO_PAGE_OFFSET as u64).map_err(|e| Error::RegisterConfiguration(e))?;
|
||||
regs::setup_fpu(&vcpu).map_err(|e| Error::FpuRegisterConfiguration(e))?;
|
||||
regs::setup_sregs(guest_mem, &vcpu).map_err(|e| Error::SegmentRegisterConfiguration(e))?;
|
||||
interrupts::set_lint(&vcpu).map_err(|e| Error::LocalIntConfiguration(e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `guest_mem` - The memory to be used by the guest.
|
||||
/// * `kernel_offset` - Offset into `guest_mem` where the kernel was loaded.
|
||||
/// * `cmdline_offset` - Offset into `guest_mem` where the kernel command line was loaded.
|
||||
/// * `cmdline_size` - Size of the kernel command line in bytes including the null terminator.
|
||||
pub fn configure_system(guest_mem: &mut [u8],
|
||||
kernel_offset: usize,
|
||||
cmdline_offset: usize,
|
||||
cmdline_size: usize)
|
||||
-> Result<()> {
|
||||
const EBDA_START: u64 = 0x0009fc00;
|
||||
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
|
||||
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
|
||||
const KERNEL_LOADER_OTHER: u8 = 0xff;
|
||||
const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x1000000; // Must be non-zero.
|
||||
const KVM_32BIT_MAX_MEM_SIZE: u64 = (1 << 32);
|
||||
const KVM_32BIT_GAP_SIZE: u64 = (768 << 20);
|
||||
const KVM_32BIT_GAP_START: u64 = (KVM_32BIT_MAX_MEM_SIZE - KVM_32BIT_GAP_SIZE);
|
||||
|
||||
let mut params: boot_params = Default::default();
|
||||
|
||||
params.hdr.type_of_loader = KERNEL_LOADER_OTHER;
|
||||
params.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
|
||||
params.hdr.header = KERNEL_HDR_MAGIC;
|
||||
params.hdr.cmd_line_ptr = cmdline_offset as u32;
|
||||
params.hdr.cmdline_size = cmdline_size as u32;
|
||||
params.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
|
||||
|
||||
add_e820_entry(&mut params, 0, EBDA_START, E820_RAM)?;
|
||||
|
||||
let mem_size = guest_mem.len() as u64;
|
||||
if mem_size < KVM_32BIT_GAP_START {
|
||||
add_e820_entry(&mut params,
|
||||
kernel_offset as u64,
|
||||
mem_size - kernel_offset as u64,
|
||||
E820_RAM)?;
|
||||
} else {
|
||||
add_e820_entry(&mut params,
|
||||
kernel_offset as u64,
|
||||
KVM_32BIT_GAP_START - kernel_offset as u64,
|
||||
E820_RAM)?;
|
||||
if mem_size > KVM_32BIT_MAX_MEM_SIZE {
|
||||
add_e820_entry(&mut params,
|
||||
KVM_32BIT_MAX_MEM_SIZE,
|
||||
mem_size - KVM_32BIT_MAX_MEM_SIZE,
|
||||
E820_RAM)?;
|
||||
}
|
||||
}
|
||||
|
||||
let zero_page_end = ZERO_PAGE_OFFSET + mem::size_of::<boot_params>();
|
||||
if zero_page_end as usize > guest_mem.len() {
|
||||
return Err(Error::ZeroPagePastRamEnd);
|
||||
}
|
||||
let mut zero_page_slice = &mut guest_mem[ZERO_PAGE_OFFSET..zero_page_end as usize];
|
||||
unsafe {
|
||||
// Dereferencing the pointer to params is safe here because it is valid, it can't be
|
||||
// destroyed after it is created at the top of this function, and we drop it as soon as the
|
||||
// data is written.
|
||||
let ptr = ¶ms as *const boot_params as *const u8;
|
||||
let bp_slice: &[u8] = std::slice::from_raw_parts(ptr, mem::size_of::<boot_params>());
|
||||
zero_page_slice.write_all(bp_slice)
|
||||
.map_err(|_| Error::ZeroPageSetup)?;
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add an e820 region to the e820 map.
|
||||
/// Returns Ok(()) if successful, or an error if there is no space left in the map.
|
||||
fn add_e820_entry(params: &mut boot_params, addr: u64, size: u64, mem_type: u32) -> Result<()> {
|
||||
if params.e820_entries >= params.e820_map.len() as u8 {
|
||||
return Err(Error::E820Configuration);
|
||||
}
|
||||
|
||||
params.e820_map[params.e820_entries as usize].addr = addr;
|
||||
params.e820_map[params.e820_entries as usize].size = size;
|
||||
params.e820_map[params.e820_entries as usize].type_ = mem_type;
|
||||
params.e820_entries += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
543
x86_64/src/msr_index.rs
Normal file
543
x86_64/src/msr_index.rs
Normal file
|
@ -0,0 +1,543 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* automatically generated by rust-bindgen
|
||||
* From upstream linux msr-index.h at commit:
|
||||
* 806276b7f07a39a1cc3f38bb1ef5c573d4594a38
|
||||
*/
|
||||
|
||||
pub const MSR_EFER: ::std::os::raw::c_uint = 0xc0000080;
|
||||
pub const MSR_STAR: ::std::os::raw::c_uint = 0xc0000081;
|
||||
pub const MSR_LSTAR: ::std::os::raw::c_uint = 0xc0000082;
|
||||
pub const MSR_CSTAR: ::std::os::raw::c_uint = 0xc0000083;
|
||||
pub const MSR_SYSCALL_MASK: ::std::os::raw::c_uint = 0xc0000084;
|
||||
pub const MSR_FS_BASE: ::std::os::raw::c_uint = 0xc0000100;
|
||||
pub const MSR_GS_BASE: ::std::os::raw::c_uint = 0xc0000101;
|
||||
pub const MSR_KERNEL_GS_BASE: ::std::os::raw::c_uint = 0xc0000102;
|
||||
pub const MSR_TSC_AUX: ::std::os::raw::c_uint = 0xc0000103;
|
||||
pub const _EFER_SCE: ::std::os::raw::c_uint = 0x00000000;
|
||||
pub const _EFER_LME: ::std::os::raw::c_uint = 0x00000008;
|
||||
pub const _EFER_LMA: ::std::os::raw::c_uint = 0x0000000a;
|
||||
pub const _EFER_NX: ::std::os::raw::c_uint = 0x0000000b;
|
||||
pub const _EFER_SVME: ::std::os::raw::c_uint = 0x0000000c;
|
||||
pub const _EFER_LMSLE: ::std::os::raw::c_uint = 0x0000000d;
|
||||
pub const _EFER_FFXSR: ::std::os::raw::c_uint = 0x0000000e;
|
||||
pub const EFER_SCE: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const EFER_LME: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const EFER_LMA: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const EFER_NX: ::std::os::raw::c_uint = 0x00000800;
|
||||
pub const EFER_SVME: ::std::os::raw::c_uint = 0x00001000;
|
||||
pub const EFER_LMSLE: ::std::os::raw::c_uint = 0x00002000;
|
||||
pub const EFER_FFXSR: ::std::os::raw::c_uint = 0x00004000;
|
||||
pub const MSR_PPIN_CTL: ::std::os::raw::c_uint = 0x0000004e;
|
||||
pub const MSR_PPIN: ::std::os::raw::c_uint = 0x0000004f;
|
||||
pub const MSR_IA32_PERFCTR0: ::std::os::raw::c_uint = 0x000000c1;
|
||||
pub const MSR_IA32_PERFCTR1: ::std::os::raw::c_uint = 0x000000c2;
|
||||
pub const MSR_FSB_FREQ: ::std::os::raw::c_uint = 0x000000cd;
|
||||
pub const MSR_PLATFORM_INFO: ::std::os::raw::c_uint = 0x000000ce;
|
||||
pub const MSR_PKG_CST_CONFIG_CONTROL: ::std::os::raw::c_uint = 0x000000e2;
|
||||
pub const NHM_C3_AUTO_DEMOTE: ::std::os::raw::c_uint = 0x02000000;
|
||||
pub const NHM_C1_AUTO_DEMOTE: ::std::os::raw::c_uint = 0x04000000;
|
||||
pub const ATM_LNC_C6_AUTO_DEMOTE: ::std::os::raw::c_uint = 0x02000000;
|
||||
pub const SNB_C1_AUTO_UNDEMOTE: ::std::os::raw::c_uint = 0x08000000;
|
||||
pub const SNB_C3_AUTO_UNDEMOTE: ::std::os::raw::c_uint = 0x10000000;
|
||||
pub const MSR_MTRRcap: ::std::os::raw::c_uint = 0x000000fe;
|
||||
pub const MSR_IA32_BBL_CR_CTL: ::std::os::raw::c_uint = 0x00000119;
|
||||
pub const MSR_IA32_BBL_CR_CTL3: ::std::os::raw::c_uint = 0x0000011e;
|
||||
pub const MSR_IA32_SYSENTER_CS: ::std::os::raw::c_uint = 0x00000174;
|
||||
pub const MSR_IA32_SYSENTER_ESP: ::std::os::raw::c_uint = 0x00000175;
|
||||
pub const MSR_IA32_SYSENTER_EIP: ::std::os::raw::c_uint = 0x00000176;
|
||||
pub const MSR_IA32_MCG_CAP: ::std::os::raw::c_uint = 0x00000179;
|
||||
pub const MSR_IA32_MCG_STATUS: ::std::os::raw::c_uint = 0x0000017a;
|
||||
pub const MSR_IA32_MCG_CTL: ::std::os::raw::c_uint = 0x0000017b;
|
||||
pub const MSR_IA32_MCG_EXT_CTL: ::std::os::raw::c_uint = 0x000004d0;
|
||||
pub const MSR_OFFCORE_RSP_0: ::std::os::raw::c_uint = 0x000001a6;
|
||||
pub const MSR_OFFCORE_RSP_1: ::std::os::raw::c_uint = 0x000001a7;
|
||||
pub const MSR_TURBO_RATIO_LIMIT: ::std::os::raw::c_uint = 0x000001ad;
|
||||
pub const MSR_TURBO_RATIO_LIMIT1: ::std::os::raw::c_uint = 0x000001ae;
|
||||
pub const MSR_TURBO_RATIO_LIMIT2: ::std::os::raw::c_uint = 0x000001af;
|
||||
pub const MSR_LBR_SELECT: ::std::os::raw::c_uint = 0x000001c8;
|
||||
pub const MSR_LBR_TOS: ::std::os::raw::c_uint = 0x000001c9;
|
||||
pub const MSR_LBR_NHM_FROM: ::std::os::raw::c_uint = 0x00000680;
|
||||
pub const MSR_LBR_NHM_TO: ::std::os::raw::c_uint = 0x000006c0;
|
||||
pub const MSR_LBR_CORE_FROM: ::std::os::raw::c_uint = 0x00000040;
|
||||
pub const MSR_LBR_CORE_TO: ::std::os::raw::c_uint = 0x00000060;
|
||||
pub const MSR_LBR_INFO_0: ::std::os::raw::c_uint = 0x00000dc0;
|
||||
pub const LBR_INFO_CYCLES: ::std::os::raw::c_uint = 0x0000ffff;
|
||||
pub const MSR_IA32_PEBS_ENABLE: ::std::os::raw::c_uint = 0x000003f1;
|
||||
pub const MSR_IA32_DS_AREA: ::std::os::raw::c_uint = 0x00000600;
|
||||
pub const MSR_IA32_PERF_CAPABILITIES: ::std::os::raw::c_uint = 0x00000345;
|
||||
pub const MSR_PEBS_LD_LAT_THRESHOLD: ::std::os::raw::c_uint = 0x000003f6;
|
||||
pub const MSR_IA32_RTIT_CTL: ::std::os::raw::c_uint = 0x00000570;
|
||||
pub const MSR_IA32_RTIT_STATUS: ::std::os::raw::c_uint = 0x00000571;
|
||||
pub const MSR_IA32_RTIT_ADDR0_A: ::std::os::raw::c_uint = 0x00000580;
|
||||
pub const MSR_IA32_RTIT_ADDR0_B: ::std::os::raw::c_uint = 0x00000581;
|
||||
pub const MSR_IA32_RTIT_ADDR1_A: ::std::os::raw::c_uint = 0x00000582;
|
||||
pub const MSR_IA32_RTIT_ADDR1_B: ::std::os::raw::c_uint = 0x00000583;
|
||||
pub const MSR_IA32_RTIT_ADDR2_A: ::std::os::raw::c_uint = 0x00000584;
|
||||
pub const MSR_IA32_RTIT_ADDR2_B: ::std::os::raw::c_uint = 0x00000585;
|
||||
pub const MSR_IA32_RTIT_ADDR3_A: ::std::os::raw::c_uint = 0x00000586;
|
||||
pub const MSR_IA32_RTIT_ADDR3_B: ::std::os::raw::c_uint = 0x00000587;
|
||||
pub const MSR_IA32_RTIT_CR3_MATCH: ::std::os::raw::c_uint = 0x00000572;
|
||||
pub const MSR_IA32_RTIT_OUTPUT_BASE: ::std::os::raw::c_uint = 0x00000560;
|
||||
pub const MSR_IA32_RTIT_OUTPUT_MASK: ::std::os::raw::c_uint = 0x00000561;
|
||||
pub const MSR_MTRRfix64K_00000: ::std::os::raw::c_uint = 0x00000250;
|
||||
pub const MSR_MTRRfix16K_80000: ::std::os::raw::c_uint = 0x00000258;
|
||||
pub const MSR_MTRRfix16K_A0000: ::std::os::raw::c_uint = 0x00000259;
|
||||
pub const MSR_MTRRfix4K_C0000: ::std::os::raw::c_uint = 0x00000268;
|
||||
pub const MSR_MTRRfix4K_C8000: ::std::os::raw::c_uint = 0x00000269;
|
||||
pub const MSR_MTRRfix4K_D0000: ::std::os::raw::c_uint = 0x0000026a;
|
||||
pub const MSR_MTRRfix4K_D8000: ::std::os::raw::c_uint = 0x0000026b;
|
||||
pub const MSR_MTRRfix4K_E0000: ::std::os::raw::c_uint = 0x0000026c;
|
||||
pub const MSR_MTRRfix4K_E8000: ::std::os::raw::c_uint = 0x0000026d;
|
||||
pub const MSR_MTRRfix4K_F0000: ::std::os::raw::c_uint = 0x0000026e;
|
||||
pub const MSR_MTRRfix4K_F8000: ::std::os::raw::c_uint = 0x0000026f;
|
||||
pub const MSR_MTRRdefType: ::std::os::raw::c_uint = 0x000002ff;
|
||||
pub const MSR_IA32_CR_PAT: ::std::os::raw::c_uint = 0x00000277;
|
||||
pub const MSR_IA32_DEBUGCTLMSR: ::std::os::raw::c_uint = 0x000001d9;
|
||||
pub const MSR_IA32_LASTBRANCHFROMIP: ::std::os::raw::c_uint = 0x000001db;
|
||||
pub const MSR_IA32_LASTBRANCHTOIP: ::std::os::raw::c_uint = 0x000001dc;
|
||||
pub const MSR_IA32_LASTINTFROMIP: ::std::os::raw::c_uint = 0x000001dd;
|
||||
pub const MSR_IA32_LASTINTTOIP: ::std::os::raw::c_uint = 0x000001de;
|
||||
pub const DEBUGCTLMSR_LBR: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const DEBUGCTLMSR_BTF: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const DEBUGCTLMSR_TR: ::std::os::raw::c_uint = 0x00000040;
|
||||
pub const DEBUGCTLMSR_BTS: ::std::os::raw::c_uint = 0x00000080;
|
||||
pub const DEBUGCTLMSR_BTINT: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const DEBUGCTLMSR_BTS_OFF_OS: ::std::os::raw::c_uint = 0x00000200;
|
||||
pub const DEBUGCTLMSR_BTS_OFF_USR: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const DEBUGCTLMSR_FREEZE_LBRS_ON_PMI: ::std::os::raw::c_uint = 0x00000800;
|
||||
pub const MSR_PEBS_FRONTEND: ::std::os::raw::c_uint = 0x000003f7;
|
||||
pub const MSR_IA32_POWER_CTL: ::std::os::raw::c_uint = 0x000001fc;
|
||||
pub const MSR_IA32_MC0_CTL: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const MSR_IA32_MC0_STATUS: ::std::os::raw::c_uint = 0x00000401;
|
||||
pub const MSR_IA32_MC0_ADDR: ::std::os::raw::c_uint = 0x00000402;
|
||||
pub const MSR_IA32_MC0_MISC: ::std::os::raw::c_uint = 0x00000403;
|
||||
pub const MSR_PKG_C3_RESIDENCY: ::std::os::raw::c_uint = 0x000003f8;
|
||||
pub const MSR_PKG_C6_RESIDENCY: ::std::os::raw::c_uint = 0x000003f9;
|
||||
pub const MSR_ATOM_PKG_C6_RESIDENCY: ::std::os::raw::c_uint = 0x000003fa;
|
||||
pub const MSR_PKG_C7_RESIDENCY: ::std::os::raw::c_uint = 0x000003fa;
|
||||
pub const MSR_CORE_C3_RESIDENCY: ::std::os::raw::c_uint = 0x000003fc;
|
||||
pub const MSR_CORE_C6_RESIDENCY: ::std::os::raw::c_uint = 0x000003fd;
|
||||
pub const MSR_CORE_C7_RESIDENCY: ::std::os::raw::c_uint = 0x000003fe;
|
||||
pub const MSR_KNL_CORE_C6_RESIDENCY: ::std::os::raw::c_uint = 0x000003ff;
|
||||
pub const MSR_PKG_C2_RESIDENCY: ::std::os::raw::c_uint = 0x0000060d;
|
||||
pub const MSR_PKG_C8_RESIDENCY: ::std::os::raw::c_uint = 0x00000630;
|
||||
pub const MSR_PKG_C9_RESIDENCY: ::std::os::raw::c_uint = 0x00000631;
|
||||
pub const MSR_PKG_C10_RESIDENCY: ::std::os::raw::c_uint = 0x00000632;
|
||||
pub const MSR_PKGC3_IRTL: ::std::os::raw::c_uint = 0x0000060a;
|
||||
pub const MSR_PKGC6_IRTL: ::std::os::raw::c_uint = 0x0000060b;
|
||||
pub const MSR_PKGC7_IRTL: ::std::os::raw::c_uint = 0x0000060c;
|
||||
pub const MSR_PKGC8_IRTL: ::std::os::raw::c_uint = 0x00000633;
|
||||
pub const MSR_PKGC9_IRTL: ::std::os::raw::c_uint = 0x00000634;
|
||||
pub const MSR_PKGC10_IRTL: ::std::os::raw::c_uint = 0x00000635;
|
||||
pub const MSR_RAPL_POWER_UNIT: ::std::os::raw::c_uint = 0x00000606;
|
||||
pub const MSR_PKG_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000610;
|
||||
pub const MSR_PKG_ENERGY_STATUS: ::std::os::raw::c_uint = 0x00000611;
|
||||
pub const MSR_PKG_PERF_STATUS: ::std::os::raw::c_uint = 0x00000613;
|
||||
pub const MSR_PKG_POWER_INFO: ::std::os::raw::c_uint = 0x00000614;
|
||||
pub const MSR_DRAM_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000618;
|
||||
pub const MSR_DRAM_ENERGY_STATUS: ::std::os::raw::c_uint = 0x00000619;
|
||||
pub const MSR_DRAM_PERF_STATUS: ::std::os::raw::c_uint = 0x0000061b;
|
||||
pub const MSR_DRAM_POWER_INFO: ::std::os::raw::c_uint = 0x0000061c;
|
||||
pub const MSR_PP0_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000638;
|
||||
pub const MSR_PP0_ENERGY_STATUS: ::std::os::raw::c_uint = 0x00000639;
|
||||
pub const MSR_PP0_POLICY: ::std::os::raw::c_uint = 0x0000063a;
|
||||
pub const MSR_PP0_PERF_STATUS: ::std::os::raw::c_uint = 0x0000063b;
|
||||
pub const MSR_PP1_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000640;
|
||||
pub const MSR_PP1_ENERGY_STATUS: ::std::os::raw::c_uint = 0x00000641;
|
||||
pub const MSR_PP1_POLICY: ::std::os::raw::c_uint = 0x00000642;
|
||||
pub const MSR_CONFIG_TDP_NOMINAL: ::std::os::raw::c_uint = 0x00000648;
|
||||
pub const MSR_CONFIG_TDP_LEVEL_1: ::std::os::raw::c_uint = 0x00000649;
|
||||
pub const MSR_CONFIG_TDP_LEVEL_2: ::std::os::raw::c_uint = 0x0000064a;
|
||||
pub const MSR_CONFIG_TDP_CONTROL: ::std::os::raw::c_uint = 0x0000064b;
|
||||
pub const MSR_TURBO_ACTIVATION_RATIO: ::std::os::raw::c_uint = 0x0000064c;
|
||||
pub const MSR_PLATFORM_ENERGY_STATUS: ::std::os::raw::c_uint = 0x0000064d;
|
||||
pub const MSR_PKG_WEIGHTED_CORE_C0_RES: ::std::os::raw::c_uint = 0x00000658;
|
||||
pub const MSR_PKG_ANY_CORE_C0_RES: ::std::os::raw::c_uint = 0x00000659;
|
||||
pub const MSR_PKG_ANY_GFXE_C0_RES: ::std::os::raw::c_uint = 0x0000065a;
|
||||
pub const MSR_PKG_BOTH_CORE_GFXE_C0_RES: ::std::os::raw::c_uint = 0x0000065b;
|
||||
pub const MSR_CORE_C1_RES: ::std::os::raw::c_uint = 0x00000660;
|
||||
pub const MSR_MODULE_C6_RES_MS: ::std::os::raw::c_uint = 0x00000664;
|
||||
pub const MSR_CC6_DEMOTION_POLICY_CONFIG: ::std::os::raw::c_uint = 0x00000668;
|
||||
pub const MSR_MC6_DEMOTION_POLICY_CONFIG: ::std::os::raw::c_uint = 0x00000669;
|
||||
pub const MSR_ATOM_CORE_RATIOS: ::std::os::raw::c_uint = 0x0000066a;
|
||||
pub const MSR_ATOM_CORE_VIDS: ::std::os::raw::c_uint = 0x0000066b;
|
||||
pub const MSR_ATOM_CORE_TURBO_RATIOS: ::std::os::raw::c_uint = 0x0000066c;
|
||||
pub const MSR_ATOM_CORE_TURBO_VIDS: ::std::os::raw::c_uint = 0x0000066d;
|
||||
pub const MSR_CORE_PERF_LIMIT_REASONS: ::std::os::raw::c_uint = 0x00000690;
|
||||
pub const MSR_GFX_PERF_LIMIT_REASONS: ::std::os::raw::c_uint = 0x000006b0;
|
||||
pub const MSR_RING_PERF_LIMIT_REASONS: ::std::os::raw::c_uint = 0x000006b1;
|
||||
pub const MSR_PPERF: ::std::os::raw::c_uint = 0x0000064e;
|
||||
pub const MSR_PERF_LIMIT_REASONS: ::std::os::raw::c_uint = 0x0000064f;
|
||||
pub const MSR_PM_ENABLE: ::std::os::raw::c_uint = 0x00000770;
|
||||
pub const MSR_HWP_CAPABILITIES: ::std::os::raw::c_uint = 0x00000771;
|
||||
pub const MSR_HWP_REQUEST_PKG: ::std::os::raw::c_uint = 0x00000772;
|
||||
pub const MSR_HWP_INTERRUPT: ::std::os::raw::c_uint = 0x00000773;
|
||||
pub const MSR_HWP_REQUEST: ::std::os::raw::c_uint = 0x00000774;
|
||||
pub const MSR_HWP_STATUS: ::std::os::raw::c_uint = 0x00000777;
|
||||
pub const HWP_BASE_BIT: ::std::os::raw::c_uint = 0x00000080;
|
||||
pub const HWP_NOTIFICATIONS_BIT: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const HWP_ACTIVITY_WINDOW_BIT: ::std::os::raw::c_uint = 0x00000200;
|
||||
pub const HWP_ENERGY_PERF_PREFERENCE_BIT: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const HWP_PACKAGE_LEVEL_REQUEST_BIT: ::std::os::raw::c_uint = 0x00000800;
|
||||
pub const MSR_AMD64_MC0_MASK: ::std::os::raw::c_uint = 0xc0010044;
|
||||
pub const MSR_IA32_MC0_CTL2: ::std::os::raw::c_uint = 0x00000280;
|
||||
pub const MSR_P6_PERFCTR0: ::std::os::raw::c_uint = 0x000000c1;
|
||||
pub const MSR_P6_PERFCTR1: ::std::os::raw::c_uint = 0x000000c2;
|
||||
pub const MSR_P6_EVNTSEL0: ::std::os::raw::c_uint = 0x00000186;
|
||||
pub const MSR_P6_EVNTSEL1: ::std::os::raw::c_uint = 0x00000187;
|
||||
pub const MSR_KNC_PERFCTR0: ::std::os::raw::c_uint = 0x00000020;
|
||||
pub const MSR_KNC_PERFCTR1: ::std::os::raw::c_uint = 0x00000021;
|
||||
pub const MSR_KNC_EVNTSEL0: ::std::os::raw::c_uint = 0x00000028;
|
||||
pub const MSR_KNC_EVNTSEL1: ::std::os::raw::c_uint = 0x00000029;
|
||||
pub const MSR_IA32_PMC0: ::std::os::raw::c_uint = 0x000004c1;
|
||||
pub const MSR_AMD64_PATCH_LEVEL: ::std::os::raw::c_uint = 0x0000008b;
|
||||
pub const MSR_AMD64_TSC_RATIO: ::std::os::raw::c_uint = 0xc0000104;
|
||||
pub const MSR_AMD64_NB_CFG: ::std::os::raw::c_uint = 0xc001001f;
|
||||
pub const MSR_AMD64_PATCH_LOADER: ::std::os::raw::c_uint = 0xc0010020;
|
||||
pub const MSR_AMD64_OSVW_ID_LENGTH: ::std::os::raw::c_uint = 0xc0010140;
|
||||
pub const MSR_AMD64_OSVW_STATUS: ::std::os::raw::c_uint = 0xc0010141;
|
||||
pub const MSR_AMD64_LS_CFG: ::std::os::raw::c_uint = 0xc0011020;
|
||||
pub const MSR_AMD64_DC_CFG: ::std::os::raw::c_uint = 0xc0011022;
|
||||
pub const MSR_AMD64_BU_CFG2: ::std::os::raw::c_uint = 0xc001102a;
|
||||
pub const MSR_AMD64_IBSFETCHCTL: ::std::os::raw::c_uint = 0xc0011030;
|
||||
pub const MSR_AMD64_IBSFETCHLINAD: ::std::os::raw::c_uint = 0xc0011031;
|
||||
pub const MSR_AMD64_IBSFETCHPHYSAD: ::std::os::raw::c_uint = 0xc0011032;
|
||||
pub const MSR_AMD64_IBSFETCH_REG_COUNT: ::std::os::raw::c_uint = 0x00000003;
|
||||
pub const MSR_AMD64_IBSFETCH_REG_MASK: ::std::os::raw::c_uint = 0x00000007;
|
||||
pub const MSR_AMD64_IBSOPCTL: ::std::os::raw::c_uint = 0xc0011033;
|
||||
pub const MSR_AMD64_IBSOPRIP: ::std::os::raw::c_uint = 0xc0011034;
|
||||
pub const MSR_AMD64_IBSOPDATA: ::std::os::raw::c_uint = 0xc0011035;
|
||||
pub const MSR_AMD64_IBSOPDATA2: ::std::os::raw::c_uint = 0xc0011036;
|
||||
pub const MSR_AMD64_IBSOPDATA3: ::std::os::raw::c_uint = 0xc0011037;
|
||||
pub const MSR_AMD64_IBSDCLINAD: ::std::os::raw::c_uint = 0xc0011038;
|
||||
pub const MSR_AMD64_IBSDCPHYSAD: ::std::os::raw::c_uint = 0xc0011039;
|
||||
pub const MSR_AMD64_IBSOP_REG_COUNT: ::std::os::raw::c_uint = 0x00000007;
|
||||
pub const MSR_AMD64_IBSOP_REG_MASK: ::std::os::raw::c_uint = 0x0000007f;
|
||||
pub const MSR_AMD64_IBSCTL: ::std::os::raw::c_uint = 0xc001103a;
|
||||
pub const MSR_AMD64_IBSBRTARGET: ::std::os::raw::c_uint = 0xc001103b;
|
||||
pub const MSR_AMD64_IBSOPDATA4: ::std::os::raw::c_uint = 0xc001103d;
|
||||
pub const MSR_AMD64_IBS_REG_COUNT_MAX: ::std::os::raw::c_uint = 0x00000008;
|
||||
pub const MSR_F17H_IRPERF: ::std::os::raw::c_uint = 0xc00000e9;
|
||||
pub const MSR_F16H_L2I_PERF_CTL: ::std::os::raw::c_uint = 0xc0010230;
|
||||
pub const MSR_F16H_L2I_PERF_CTR: ::std::os::raw::c_uint = 0xc0010231;
|
||||
pub const MSR_F16H_DR1_ADDR_MASK: ::std::os::raw::c_uint = 0xc0011019;
|
||||
pub const MSR_F16H_DR2_ADDR_MASK: ::std::os::raw::c_uint = 0xc001101a;
|
||||
pub const MSR_F16H_DR3_ADDR_MASK: ::std::os::raw::c_uint = 0xc001101b;
|
||||
pub const MSR_F16H_DR0_ADDR_MASK: ::std::os::raw::c_uint = 0xc0011027;
|
||||
pub const MSR_F15H_PERF_CTL: ::std::os::raw::c_uint = 0xc0010200;
|
||||
pub const MSR_F15H_PERF_CTR: ::std::os::raw::c_uint = 0xc0010201;
|
||||
pub const MSR_F15H_NB_PERF_CTL: ::std::os::raw::c_uint = 0xc0010240;
|
||||
pub const MSR_F15H_NB_PERF_CTR: ::std::os::raw::c_uint = 0xc0010241;
|
||||
pub const MSR_F15H_PTSC: ::std::os::raw::c_uint = 0xc0010280;
|
||||
pub const MSR_F15H_IC_CFG: ::std::os::raw::c_uint = 0xc0011021;
|
||||
pub const MSR_FAM10H_MMIO_CONF_BASE: ::std::os::raw::c_uint = 0xc0010058;
|
||||
pub const FAM10H_MMIO_CONF_ENABLE: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const FAM10H_MMIO_CONF_BUSRANGE_MASK: ::std::os::raw::c_uint = 0x0000000f;
|
||||
pub const FAM10H_MMIO_CONF_BUSRANGE_SHIFT: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const FAM10H_MMIO_CONF_BASE_MASK: ::std::os::raw::c_uint = 0x0fffffff;
|
||||
pub const FAM10H_MMIO_CONF_BASE_SHIFT: ::std::os::raw::c_uint = 0x00000014;
|
||||
pub const MSR_FAM10H_NODE_ID: ::std::os::raw::c_uint = 0xc001100c;
|
||||
pub const MSR_K8_TOP_MEM1: ::std::os::raw::c_uint = 0xc001001a;
|
||||
pub const MSR_K8_TOP_MEM2: ::std::os::raw::c_uint = 0xc001001d;
|
||||
pub const MSR_K8_SYSCFG: ::std::os::raw::c_uint = 0xc0010010;
|
||||
pub const MSR_K8_INT_PENDING_MSG: ::std::os::raw::c_uint = 0xc0010055;
|
||||
pub const K8_INTP_C1E_ACTIVE_MASK: ::std::os::raw::c_uint = 0x18000000;
|
||||
pub const MSR_K8_TSEG_ADDR: ::std::os::raw::c_uint = 0xc0010112;
|
||||
pub const MSR_K8_TSEG_MASK: ::std::os::raw::c_uint = 0xc0010113;
|
||||
pub const K8_MTRRFIXRANGE_DRAM_ENABLE: ::std::os::raw::c_uint = 0x00040000;
|
||||
pub const K8_MTRRFIXRANGE_DRAM_MODIFY: ::std::os::raw::c_uint = 0x00080000;
|
||||
pub const K8_MTRR_RDMEM_WRMEM_MASK: ::std::os::raw::c_uint = 0x18181818;
|
||||
pub const MSR_K7_EVNTSEL0: ::std::os::raw::c_uint = 0xc0010000;
|
||||
pub const MSR_K7_PERFCTR0: ::std::os::raw::c_uint = 0xc0010004;
|
||||
pub const MSR_K7_EVNTSEL1: ::std::os::raw::c_uint = 0xc0010001;
|
||||
pub const MSR_K7_PERFCTR1: ::std::os::raw::c_uint = 0xc0010005;
|
||||
pub const MSR_K7_EVNTSEL2: ::std::os::raw::c_uint = 0xc0010002;
|
||||
pub const MSR_K7_PERFCTR2: ::std::os::raw::c_uint = 0xc0010006;
|
||||
pub const MSR_K7_EVNTSEL3: ::std::os::raw::c_uint = 0xc0010003;
|
||||
pub const MSR_K7_PERFCTR3: ::std::os::raw::c_uint = 0xc0010007;
|
||||
pub const MSR_K7_CLK_CTL: ::std::os::raw::c_uint = 0xc001001b;
|
||||
pub const MSR_K7_HWCR: ::std::os::raw::c_uint = 0xc0010015;
|
||||
pub const MSR_K7_FID_VID_CTL: ::std::os::raw::c_uint = 0xc0010041;
|
||||
pub const MSR_K7_FID_VID_STATUS: ::std::os::raw::c_uint = 0xc0010042;
|
||||
pub const MSR_K6_WHCR: ::std::os::raw::c_uint = 0xc0000082;
|
||||
pub const MSR_K6_UWCCR: ::std::os::raw::c_uint = 0xc0000085;
|
||||
pub const MSR_K6_EPMR: ::std::os::raw::c_uint = 0xc0000086;
|
||||
pub const MSR_K6_PSOR: ::std::os::raw::c_uint = 0xc0000087;
|
||||
pub const MSR_K6_PFIR: ::std::os::raw::c_uint = 0xc0000088;
|
||||
pub const MSR_IDT_FCR1: ::std::os::raw::c_uint = 0x00000107;
|
||||
pub const MSR_IDT_FCR2: ::std::os::raw::c_uint = 0x00000108;
|
||||
pub const MSR_IDT_FCR3: ::std::os::raw::c_uint = 0x00000109;
|
||||
pub const MSR_IDT_FCR4: ::std::os::raw::c_uint = 0x0000010a;
|
||||
pub const MSR_IDT_MCR0: ::std::os::raw::c_uint = 0x00000110;
|
||||
pub const MSR_IDT_MCR1: ::std::os::raw::c_uint = 0x00000111;
|
||||
pub const MSR_IDT_MCR2: ::std::os::raw::c_uint = 0x00000112;
|
||||
pub const MSR_IDT_MCR3: ::std::os::raw::c_uint = 0x00000113;
|
||||
pub const MSR_IDT_MCR4: ::std::os::raw::c_uint = 0x00000114;
|
||||
pub const MSR_IDT_MCR5: ::std::os::raw::c_uint = 0x00000115;
|
||||
pub const MSR_IDT_MCR6: ::std::os::raw::c_uint = 0x00000116;
|
||||
pub const MSR_IDT_MCR7: ::std::os::raw::c_uint = 0x00000117;
|
||||
pub const MSR_IDT_MCR_CTRL: ::std::os::raw::c_uint = 0x00000120;
|
||||
pub const MSR_VIA_FCR: ::std::os::raw::c_uint = 0x00001107;
|
||||
pub const MSR_VIA_LONGHAUL: ::std::os::raw::c_uint = 0x0000110a;
|
||||
pub const MSR_VIA_RNG: ::std::os::raw::c_uint = 0x0000110b;
|
||||
pub const MSR_VIA_BCR2: ::std::os::raw::c_uint = 0x00001147;
|
||||
pub const MSR_TMTA_LONGRUN_CTRL: ::std::os::raw::c_uint = 0x80868010;
|
||||
pub const MSR_TMTA_LONGRUN_FLAGS: ::std::os::raw::c_uint = 0x80868011;
|
||||
pub const MSR_TMTA_LRTI_READOUT: ::std::os::raw::c_uint = 0x80868018;
|
||||
pub const MSR_TMTA_LRTI_VOLT_MHZ: ::std::os::raw::c_uint = 0x8086801a;
|
||||
pub const MSR_IA32_P5_MC_ADDR: ::std::os::raw::c_uint = 0x00000000;
|
||||
pub const MSR_IA32_P5_MC_TYPE: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const MSR_IA32_TSC: ::std::os::raw::c_uint = 0x00000010;
|
||||
pub const MSR_IA32_PLATFORM_ID: ::std::os::raw::c_uint = 0x00000017;
|
||||
pub const MSR_IA32_EBL_CR_POWERON: ::std::os::raw::c_uint = 0x0000002a;
|
||||
pub const MSR_EBC_FREQUENCY_ID: ::std::os::raw::c_uint = 0x0000002c;
|
||||
pub const MSR_SMI_COUNT: ::std::os::raw::c_uint = 0x00000034;
|
||||
pub const MSR_IA32_FEATURE_CONTROL: ::std::os::raw::c_uint = 0x0000003a;
|
||||
pub const MSR_IA32_TSC_ADJUST: ::std::os::raw::c_uint = 0x0000003b;
|
||||
pub const MSR_IA32_BNDCFGS: ::std::os::raw::c_uint = 0x00000d90;
|
||||
pub const MSR_IA32_XSS: ::std::os::raw::c_uint = 0x00000da0;
|
||||
pub const FEATURE_CONTROL_LOCKED: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX: ::std::os::raw::c_uint = 0x00000004;
|
||||
pub const FEATURE_CONTROL_LMCE: ::std::os::raw::c_uint = 0x00100000;
|
||||
pub const MSR_IA32_APICBASE: ::std::os::raw::c_uint = 0x0000001b;
|
||||
pub const MSR_IA32_APICBASE_BSP: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const MSR_IA32_APICBASE_ENABLE: ::std::os::raw::c_uint = 0x00000800;
|
||||
pub const MSR_IA32_APICBASE_BASE: ::std::os::raw::c_uint = 0xfffff000;
|
||||
pub const MSR_IA32_TSCDEADLINE: ::std::os::raw::c_uint = 0x000006e0;
|
||||
pub const MSR_IA32_UCODE_WRITE: ::std::os::raw::c_uint = 0x00000079;
|
||||
pub const MSR_IA32_UCODE_REV: ::std::os::raw::c_uint = 0x0000008b;
|
||||
pub const MSR_IA32_SMM_MONITOR_CTL: ::std::os::raw::c_uint = 0x0000009b;
|
||||
pub const MSR_IA32_SMBASE: ::std::os::raw::c_uint = 0x0000009e;
|
||||
pub const MSR_IA32_PERF_STATUS: ::std::os::raw::c_uint = 0x00000198;
|
||||
pub const MSR_IA32_PERF_CTL: ::std::os::raw::c_uint = 0x00000199;
|
||||
pub const INTEL_PERF_CTL_MASK: ::std::os::raw::c_uint = 0x0000ffff;
|
||||
pub const MSR_AMD_PSTATE_DEF_BASE: ::std::os::raw::c_uint = 0xc0010064;
|
||||
pub const MSR_AMD_PERF_STATUS: ::std::os::raw::c_uint = 0xc0010063;
|
||||
pub const MSR_AMD_PERF_CTL: ::std::os::raw::c_uint = 0xc0010062;
|
||||
pub const MSR_IA32_MPERF: ::std::os::raw::c_uint = 0x000000e7;
|
||||
pub const MSR_IA32_APERF: ::std::os::raw::c_uint = 0x000000e8;
|
||||
pub const MSR_IA32_THERM_CONTROL: ::std::os::raw::c_uint = 0x0000019a;
|
||||
pub const MSR_IA32_THERM_INTERRUPT: ::std::os::raw::c_uint = 0x0000019b;
|
||||
pub const THERM_INT_HIGH_ENABLE: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const THERM_INT_LOW_ENABLE: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const THERM_INT_PLN_ENABLE: ::std::os::raw::c_uint = 0x01000000;
|
||||
pub const MSR_IA32_THERM_STATUS: ::std::os::raw::c_uint = 0x0000019c;
|
||||
pub const THERM_STATUS_PROCHOT: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const THERM_STATUS_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const MSR_THERM2_CTL: ::std::os::raw::c_uint = 0x0000019d;
|
||||
pub const MSR_THERM2_CTL_TM_SELECT: ::std::os::raw::c_uint = 0x00010000;
|
||||
pub const MSR_IA32_MISC_ENABLE: ::std::os::raw::c_uint = 0x000001a0;
|
||||
pub const MSR_IA32_TEMPERATURE_TARGET: ::std::os::raw::c_uint = 0x000001a2;
|
||||
pub const MSR_MISC_FEATURE_CONTROL: ::std::os::raw::c_uint = 0x000001a4;
|
||||
pub const MSR_MISC_PWR_MGMT: ::std::os::raw::c_uint = 0x000001aa;
|
||||
pub const MSR_IA32_ENERGY_PERF_BIAS: ::std::os::raw::c_uint = 0x000001b0;
|
||||
pub const ENERGY_PERF_BIAS_PERFORMANCE: ::std::os::raw::c_uint = 0x00000000;
|
||||
pub const ENERGY_PERF_BIAS_NORMAL: ::std::os::raw::c_uint = 0x00000006;
|
||||
pub const ENERGY_PERF_BIAS_POWERSAVE: ::std::os::raw::c_uint = 0x0000000f;
|
||||
pub const MSR_IA32_PACKAGE_THERM_STATUS: ::std::os::raw::c_uint = 0x000001b1;
|
||||
pub const PACKAGE_THERM_STATUS_PROCHOT: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const PACKAGE_THERM_STATUS_POWER_LIMIT: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const MSR_IA32_PACKAGE_THERM_INTERRUPT: ::std::os::raw::c_uint = 0x000001b2;
|
||||
pub const PACKAGE_THERM_INT_HIGH_ENABLE: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const PACKAGE_THERM_INT_LOW_ENABLE: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const PACKAGE_THERM_INT_PLN_ENABLE: ::std::os::raw::c_uint = 0x01000000;
|
||||
pub const THERM_INT_THRESHOLD0_ENABLE: ::std::os::raw::c_uint = 0x00008000;
|
||||
pub const THERM_SHIFT_THRESHOLD0: ::std::os::raw::c_uint = 0x00000008;
|
||||
pub const THERM_MASK_THRESHOLD0: ::std::os::raw::c_uint = 0x00007f00;
|
||||
pub const THERM_INT_THRESHOLD1_ENABLE: ::std::os::raw::c_uint = 0x00800000;
|
||||
pub const THERM_SHIFT_THRESHOLD1: ::std::os::raw::c_uint = 0x00000010;
|
||||
pub const THERM_MASK_THRESHOLD1: ::std::os::raw::c_uint = 0x007f0000;
|
||||
pub const THERM_STATUS_THRESHOLD0: ::std::os::raw::c_uint = 0x00000040;
|
||||
pub const THERM_LOG_THRESHOLD0: ::std::os::raw::c_uint = 0x00000080;
|
||||
pub const THERM_STATUS_THRESHOLD1: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const THERM_LOG_THRESHOLD1: ::std::os::raw::c_uint = 0x00000200;
|
||||
pub const MSR_IA32_MISC_ENABLE_FAST_STRING_BIT: ::std::os::raw::c_uint = 0x00000000;
|
||||
pub const MSR_IA32_MISC_ENABLE_FAST_STRING: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const MSR_IA32_MISC_ENABLE_TCC_BIT: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const MSR_IA32_MISC_ENABLE_TCC: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const MSR_IA32_MISC_ENABLE_EMON_BIT: ::std::os::raw::c_uint = 0x00000007;
|
||||
pub const MSR_IA32_MISC_ENABLE_EMON: ::std::os::raw::c_uint = 0x00000080;
|
||||
pub const MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT: ::std::os::raw::c_uint = 0x0000000b;
|
||||
pub const MSR_IA32_MISC_ENABLE_BTS_UNAVAIL: ::std::os::raw::c_uint = 0x00000800;
|
||||
pub const MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT: ::std::os::raw::c_uint = 0x0000000c;
|
||||
pub const MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL: ::std::os::raw::c_uint = 0x00001000;
|
||||
pub const MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT: ::std::os::raw::c_uint = 0x00000010;
|
||||
pub const MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP: ::std::os::raw::c_uint = 0x00010000;
|
||||
pub const MSR_IA32_MISC_ENABLE_MWAIT_BIT: ::std::os::raw::c_uint = 0x00000012;
|
||||
pub const MSR_IA32_MISC_ENABLE_MWAIT: ::std::os::raw::c_uint = 0x00040000;
|
||||
pub const MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT: ::std::os::raw::c_uint = 0x00000016;
|
||||
pub const MSR_IA32_MISC_ENABLE_LIMIT_CPUID: ::std::os::raw::c_uint = 0x00400000;
|
||||
pub const MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000017;
|
||||
pub const MSR_IA32_MISC_ENABLE_XTPR_DISABLE: ::std::os::raw::c_uint = 0x00800000;
|
||||
pub const MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000022;
|
||||
pub const MSR_IA32_MISC_ENABLE_XD_DISABLE: ::std::os::raw::c_ulonglong = 0x400000000;
|
||||
pub const MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT: ::std::os::raw::c_uint = 0x00000002;
|
||||
pub const MSR_IA32_MISC_ENABLE_X87_COMPAT: ::std::os::raw::c_uint = 0x00000004;
|
||||
pub const MSR_IA32_MISC_ENABLE_TM1_BIT: ::std::os::raw::c_uint = 0x00000003;
|
||||
pub const MSR_IA32_MISC_ENABLE_TM1: ::std::os::raw::c_uint = 0x00000008;
|
||||
pub const MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000004;
|
||||
pub const MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE: ::std::os::raw::c_uint = 0x00000010;
|
||||
pub const MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000006;
|
||||
pub const MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE: ::std::os::raw::c_uint = 0x00000040;
|
||||
pub const MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT: ::std::os::raw::c_uint = 0x00000008;
|
||||
pub const MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK: ::std::os::raw::c_uint = 0x00000100;
|
||||
pub const MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000009;
|
||||
pub const MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE: ::std::os::raw::c_uint = 0x00000200;
|
||||
pub const MSR_IA32_MISC_ENABLE_FERR_BIT: ::std::os::raw::c_uint = 0x0000000a;
|
||||
pub const MSR_IA32_MISC_ENABLE_FERR: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT: ::std::os::raw::c_uint = 0x0000000a;
|
||||
pub const MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX: ::std::os::raw::c_uint = 0x00000400;
|
||||
pub const MSR_IA32_MISC_ENABLE_TM2_BIT: ::std::os::raw::c_uint = 0x0000000d;
|
||||
pub const MSR_IA32_MISC_ENABLE_TM2: ::std::os::raw::c_uint = 0x00002000;
|
||||
pub const MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000013;
|
||||
pub const MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE: ::std::os::raw::c_uint = 0x00080000;
|
||||
pub const MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT: ::std::os::raw::c_uint = 0x00000014;
|
||||
pub const MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK: ::std::os::raw::c_uint = 0x00100000;
|
||||
pub const MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT: ::std::os::raw::c_uint = 0x00000018;
|
||||
pub const MSR_IA32_MISC_ENABLE_L1D_CONTEXT: ::std::os::raw::c_uint = 0x01000000;
|
||||
pub const MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000025;
|
||||
pub const MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE: ::std::os::raw::c_ulonglong = 0x2000000000;
|
||||
pub const MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000026;
|
||||
pub const MSR_IA32_MISC_ENABLE_TURBO_DISABLE: ::std::os::raw::c_ulonglong = 0x4000000000;
|
||||
pub const MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT: ::std::os::raw::c_uint = 0x00000027;
|
||||
pub const MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE: ::std::os::raw::c_ulonglong = 0x8000000000;
|
||||
pub const MSR_MISC_FEATURE_ENABLES: ::std::os::raw::c_uint = 0x00000140;
|
||||
pub const MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT: ::std::os::raw::c_uint = 0x00000001;
|
||||
pub const MSR_IA32_TSC_DEADLINE: ::std::os::raw::c_uint = 0x000006e0;
|
||||
pub const MSR_IA32_MCG_EAX: ::std::os::raw::c_uint = 0x00000180;
|
||||
pub const MSR_IA32_MCG_EBX: ::std::os::raw::c_uint = 0x00000181;
|
||||
pub const MSR_IA32_MCG_ECX: ::std::os::raw::c_uint = 0x00000182;
|
||||
pub const MSR_IA32_MCG_EDX: ::std::os::raw::c_uint = 0x00000183;
|
||||
pub const MSR_IA32_MCG_ESI: ::std::os::raw::c_uint = 0x00000184;
|
||||
pub const MSR_IA32_MCG_EDI: ::std::os::raw::c_uint = 0x00000185;
|
||||
pub const MSR_IA32_MCG_EBP: ::std::os::raw::c_uint = 0x00000186;
|
||||
pub const MSR_IA32_MCG_ESP: ::std::os::raw::c_uint = 0x00000187;
|
||||
pub const MSR_IA32_MCG_EFLAGS: ::std::os::raw::c_uint = 0x00000188;
|
||||
pub const MSR_IA32_MCG_EIP: ::std::os::raw::c_uint = 0x00000189;
|
||||
pub const MSR_IA32_MCG_RESERVED: ::std::os::raw::c_uint = 0x0000018a;
|
||||
pub const MSR_P4_BPU_PERFCTR0: ::std::os::raw::c_uint = 0x00000300;
|
||||
pub const MSR_P4_BPU_PERFCTR1: ::std::os::raw::c_uint = 0x00000301;
|
||||
pub const MSR_P4_BPU_PERFCTR2: ::std::os::raw::c_uint = 0x00000302;
|
||||
pub const MSR_P4_BPU_PERFCTR3: ::std::os::raw::c_uint = 0x00000303;
|
||||
pub const MSR_P4_MS_PERFCTR0: ::std::os::raw::c_uint = 0x00000304;
|
||||
pub const MSR_P4_MS_PERFCTR1: ::std::os::raw::c_uint = 0x00000305;
|
||||
pub const MSR_P4_MS_PERFCTR2: ::std::os::raw::c_uint = 0x00000306;
|
||||
pub const MSR_P4_MS_PERFCTR3: ::std::os::raw::c_uint = 0x00000307;
|
||||
pub const MSR_P4_FLAME_PERFCTR0: ::std::os::raw::c_uint = 0x00000308;
|
||||
pub const MSR_P4_FLAME_PERFCTR1: ::std::os::raw::c_uint = 0x00000309;
|
||||
pub const MSR_P4_FLAME_PERFCTR2: ::std::os::raw::c_uint = 0x0000030a;
|
||||
pub const MSR_P4_FLAME_PERFCTR3: ::std::os::raw::c_uint = 0x0000030b;
|
||||
pub const MSR_P4_IQ_PERFCTR0: ::std::os::raw::c_uint = 0x0000030c;
|
||||
pub const MSR_P4_IQ_PERFCTR1: ::std::os::raw::c_uint = 0x0000030d;
|
||||
pub const MSR_P4_IQ_PERFCTR2: ::std::os::raw::c_uint = 0x0000030e;
|
||||
pub const MSR_P4_IQ_PERFCTR3: ::std::os::raw::c_uint = 0x0000030f;
|
||||
pub const MSR_P4_IQ_PERFCTR4: ::std::os::raw::c_uint = 0x00000310;
|
||||
pub const MSR_P4_IQ_PERFCTR5: ::std::os::raw::c_uint = 0x00000311;
|
||||
pub const MSR_P4_BPU_CCCR0: ::std::os::raw::c_uint = 0x00000360;
|
||||
pub const MSR_P4_BPU_CCCR1: ::std::os::raw::c_uint = 0x00000361;
|
||||
pub const MSR_P4_BPU_CCCR2: ::std::os::raw::c_uint = 0x00000362;
|
||||
pub const MSR_P4_BPU_CCCR3: ::std::os::raw::c_uint = 0x00000363;
|
||||
pub const MSR_P4_MS_CCCR0: ::std::os::raw::c_uint = 0x00000364;
|
||||
pub const MSR_P4_MS_CCCR1: ::std::os::raw::c_uint = 0x00000365;
|
||||
pub const MSR_P4_MS_CCCR2: ::std::os::raw::c_uint = 0x00000366;
|
||||
pub const MSR_P4_MS_CCCR3: ::std::os::raw::c_uint = 0x00000367;
|
||||
pub const MSR_P4_FLAME_CCCR0: ::std::os::raw::c_uint = 0x00000368;
|
||||
pub const MSR_P4_FLAME_CCCR1: ::std::os::raw::c_uint = 0x00000369;
|
||||
pub const MSR_P4_FLAME_CCCR2: ::std::os::raw::c_uint = 0x0000036a;
|
||||
pub const MSR_P4_FLAME_CCCR3: ::std::os::raw::c_uint = 0x0000036b;
|
||||
pub const MSR_P4_IQ_CCCR0: ::std::os::raw::c_uint = 0x0000036c;
|
||||
pub const MSR_P4_IQ_CCCR1: ::std::os::raw::c_uint = 0x0000036d;
|
||||
pub const MSR_P4_IQ_CCCR2: ::std::os::raw::c_uint = 0x0000036e;
|
||||
pub const MSR_P4_IQ_CCCR3: ::std::os::raw::c_uint = 0x0000036f;
|
||||
pub const MSR_P4_IQ_CCCR4: ::std::os::raw::c_uint = 0x00000370;
|
||||
pub const MSR_P4_IQ_CCCR5: ::std::os::raw::c_uint = 0x00000371;
|
||||
pub const MSR_P4_ALF_ESCR0: ::std::os::raw::c_uint = 0x000003ca;
|
||||
pub const MSR_P4_ALF_ESCR1: ::std::os::raw::c_uint = 0x000003cb;
|
||||
pub const MSR_P4_BPU_ESCR0: ::std::os::raw::c_uint = 0x000003b2;
|
||||
pub const MSR_P4_BPU_ESCR1: ::std::os::raw::c_uint = 0x000003b3;
|
||||
pub const MSR_P4_BSU_ESCR0: ::std::os::raw::c_uint = 0x000003a0;
|
||||
pub const MSR_P4_BSU_ESCR1: ::std::os::raw::c_uint = 0x000003a1;
|
||||
pub const MSR_P4_CRU_ESCR0: ::std::os::raw::c_uint = 0x000003b8;
|
||||
pub const MSR_P4_CRU_ESCR1: ::std::os::raw::c_uint = 0x000003b9;
|
||||
pub const MSR_P4_CRU_ESCR2: ::std::os::raw::c_uint = 0x000003cc;
|
||||
pub const MSR_P4_CRU_ESCR3: ::std::os::raw::c_uint = 0x000003cd;
|
||||
pub const MSR_P4_CRU_ESCR4: ::std::os::raw::c_uint = 0x000003e0;
|
||||
pub const MSR_P4_CRU_ESCR5: ::std::os::raw::c_uint = 0x000003e1;
|
||||
pub const MSR_P4_DAC_ESCR0: ::std::os::raw::c_uint = 0x000003a8;
|
||||
pub const MSR_P4_DAC_ESCR1: ::std::os::raw::c_uint = 0x000003a9;
|
||||
pub const MSR_P4_FIRM_ESCR0: ::std::os::raw::c_uint = 0x000003a4;
|
||||
pub const MSR_P4_FIRM_ESCR1: ::std::os::raw::c_uint = 0x000003a5;
|
||||
pub const MSR_P4_FLAME_ESCR0: ::std::os::raw::c_uint = 0x000003a6;
|
||||
pub const MSR_P4_FLAME_ESCR1: ::std::os::raw::c_uint = 0x000003a7;
|
||||
pub const MSR_P4_FSB_ESCR0: ::std::os::raw::c_uint = 0x000003a2;
|
||||
pub const MSR_P4_FSB_ESCR1: ::std::os::raw::c_uint = 0x000003a3;
|
||||
pub const MSR_P4_IQ_ESCR0: ::std::os::raw::c_uint = 0x000003ba;
|
||||
pub const MSR_P4_IQ_ESCR1: ::std::os::raw::c_uint = 0x000003bb;
|
||||
pub const MSR_P4_IS_ESCR0: ::std::os::raw::c_uint = 0x000003b4;
|
||||
pub const MSR_P4_IS_ESCR1: ::std::os::raw::c_uint = 0x000003b5;
|
||||
pub const MSR_P4_ITLB_ESCR0: ::std::os::raw::c_uint = 0x000003b6;
|
||||
pub const MSR_P4_ITLB_ESCR1: ::std::os::raw::c_uint = 0x000003b7;
|
||||
pub const MSR_P4_IX_ESCR0: ::std::os::raw::c_uint = 0x000003c8;
|
||||
pub const MSR_P4_IX_ESCR1: ::std::os::raw::c_uint = 0x000003c9;
|
||||
pub const MSR_P4_MOB_ESCR0: ::std::os::raw::c_uint = 0x000003aa;
|
||||
pub const MSR_P4_MOB_ESCR1: ::std::os::raw::c_uint = 0x000003ab;
|
||||
pub const MSR_P4_MS_ESCR0: ::std::os::raw::c_uint = 0x000003c0;
|
||||
pub const MSR_P4_MS_ESCR1: ::std::os::raw::c_uint = 0x000003c1;
|
||||
pub const MSR_P4_PMH_ESCR0: ::std::os::raw::c_uint = 0x000003ac;
|
||||
pub const MSR_P4_PMH_ESCR1: ::std::os::raw::c_uint = 0x000003ad;
|
||||
pub const MSR_P4_RAT_ESCR0: ::std::os::raw::c_uint = 0x000003bc;
|
||||
pub const MSR_P4_RAT_ESCR1: ::std::os::raw::c_uint = 0x000003bd;
|
||||
pub const MSR_P4_SAAT_ESCR0: ::std::os::raw::c_uint = 0x000003ae;
|
||||
pub const MSR_P4_SAAT_ESCR1: ::std::os::raw::c_uint = 0x000003af;
|
||||
pub const MSR_P4_SSU_ESCR0: ::std::os::raw::c_uint = 0x000003be;
|
||||
pub const MSR_P4_SSU_ESCR1: ::std::os::raw::c_uint = 0x000003bf;
|
||||
pub const MSR_P4_TBPU_ESCR0: ::std::os::raw::c_uint = 0x000003c2;
|
||||
pub const MSR_P4_TBPU_ESCR1: ::std::os::raw::c_uint = 0x000003c3;
|
||||
pub const MSR_P4_TC_ESCR0: ::std::os::raw::c_uint = 0x000003c4;
|
||||
pub const MSR_P4_TC_ESCR1: ::std::os::raw::c_uint = 0x000003c5;
|
||||
pub const MSR_P4_U2L_ESCR0: ::std::os::raw::c_uint = 0x000003b0;
|
||||
pub const MSR_P4_U2L_ESCR1: ::std::os::raw::c_uint = 0x000003b1;
|
||||
pub const MSR_P4_PEBS_MATRIX_VERT: ::std::os::raw::c_uint = 0x000003f2;
|
||||
pub const MSR_CORE_PERF_FIXED_CTR0: ::std::os::raw::c_uint = 0x00000309;
|
||||
pub const MSR_CORE_PERF_FIXED_CTR1: ::std::os::raw::c_uint = 0x0000030a;
|
||||
pub const MSR_CORE_PERF_FIXED_CTR2: ::std::os::raw::c_uint = 0x0000030b;
|
||||
pub const MSR_CORE_PERF_FIXED_CTR_CTRL: ::std::os::raw::c_uint = 0x0000038d;
|
||||
pub const MSR_CORE_PERF_GLOBAL_STATUS: ::std::os::raw::c_uint = 0x0000038e;
|
||||
pub const MSR_CORE_PERF_GLOBAL_CTRL: ::std::os::raw::c_uint = 0x0000038f;
|
||||
pub const MSR_CORE_PERF_GLOBAL_OVF_CTRL: ::std::os::raw::c_uint = 0x00000390;
|
||||
pub const MSR_GEODE_BUSCONT_CONF0: ::std::os::raw::c_uint = 0x00001900;
|
||||
pub const MSR_IA32_VMX_BASIC: ::std::os::raw::c_uint = 0x00000480;
|
||||
pub const MSR_IA32_VMX_PINBASED_CTLS: ::std::os::raw::c_uint = 0x00000481;
|
||||
pub const MSR_IA32_VMX_PROCBASED_CTLS: ::std::os::raw::c_uint = 0x00000482;
|
||||
pub const MSR_IA32_VMX_EXIT_CTLS: ::std::os::raw::c_uint = 0x00000483;
|
||||
pub const MSR_IA32_VMX_ENTRY_CTLS: ::std::os::raw::c_uint = 0x00000484;
|
||||
pub const MSR_IA32_VMX_MISC: ::std::os::raw::c_uint = 0x00000485;
|
||||
pub const MSR_IA32_VMX_CR0_FIXED0: ::std::os::raw::c_uint = 0x00000486;
|
||||
pub const MSR_IA32_VMX_CR0_FIXED1: ::std::os::raw::c_uint = 0x00000487;
|
||||
pub const MSR_IA32_VMX_CR4_FIXED0: ::std::os::raw::c_uint = 0x00000488;
|
||||
pub const MSR_IA32_VMX_CR4_FIXED1: ::std::os::raw::c_uint = 0x00000489;
|
||||
pub const MSR_IA32_VMX_VMCS_ENUM: ::std::os::raw::c_uint = 0x0000048a;
|
||||
pub const MSR_IA32_VMX_PROCBASED_CTLS2: ::std::os::raw::c_uint = 0x0000048b;
|
||||
pub const MSR_IA32_VMX_EPT_VPID_CAP: ::std::os::raw::c_uint = 0x0000048c;
|
||||
pub const MSR_IA32_VMX_TRUE_PINBASED_CTLS: ::std::os::raw::c_uint = 0x0000048d;
|
||||
pub const MSR_IA32_VMX_TRUE_PROCBASED_CTLS: ::std::os::raw::c_uint = 0x0000048e;
|
||||
pub const MSR_IA32_VMX_TRUE_EXIT_CTLS: ::std::os::raw::c_uint = 0x0000048f;
|
||||
pub const MSR_IA32_VMX_TRUE_ENTRY_CTLS: ::std::os::raw::c_uint = 0x00000490;
|
||||
pub const MSR_IA32_VMX_VMFUNC: ::std::os::raw::c_uint = 0x00000491;
|
||||
pub const VMX_BASIC_VMCS_SIZE_SHIFT: ::std::os::raw::c_uint = 0x00000020;
|
||||
pub const VMX_BASIC_TRUE_CTLS: ::std::os::raw::c_ulonglong = 0x80000000000000;
|
||||
pub const VMX_BASIC_64: ::std::os::raw::c_ulonglong = 0x1000000000000;
|
||||
pub const VMX_BASIC_MEM_TYPE_SHIFT: ::std::os::raw::c_uint = 0x00000032;
|
||||
pub const VMX_BASIC_MEM_TYPE_MASK: ::std::os::raw::c_ulonglong = 0x3c000000000000;
|
||||
pub const VMX_BASIC_MEM_TYPE_WB: ::std::os::raw::c_uint = 0x00000006;
|
||||
pub const VMX_BASIC_INOUT: ::std::os::raw::c_ulonglong = 0x40000000000000;
|
||||
pub const MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS: ::std::os::raw::c_uint = 0x20000000;
|
||||
pub const MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE: ::std::os::raw::c_uint = 0x0000001f;
|
||||
pub const MSR_VM_CR: ::std::os::raw::c_uint = 0xc0010114;
|
||||
pub const MSR_VM_IGNNE: ::std::os::raw::c_uint = 0xc0010115;
|
||||
pub const MSR_VM_HSAVE_PA: ::std::os::raw::c_uint = 0xc0010117;
|
318
x86_64/src/regs.rs
Normal file
318
x86_64/src/regs.rs
Normal file
|
@ -0,0 +1,318 @@
|
|||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::io::Cursor;
|
||||
use std::mem;
|
||||
use std::result;
|
||||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
use kvm;
|
||||
use kvm_sys::kvm_fpu;
|
||||
use kvm_sys::kvm_msr_entry;
|
||||
use kvm_sys::kvm_msrs;
|
||||
use kvm_sys::kvm_regs;
|
||||
use kvm_sys::kvm_sregs;
|
||||
use gdt;
|
||||
use sys_util;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
MsrIoctlFailed(sys_util::Error),
|
||||
FpuIoctlFailed(sys_util::Error),
|
||||
SettingRegistersIoctl(sys_util::Error),
|
||||
SRegsIoctlFailed(sys_util::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
fn create_msr_entries() -> Vec<kvm_msr_entry> {
|
||||
let mut entries = Vec::<kvm_msr_entry>::new();
|
||||
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_IA32_SYSENTER_CS,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_IA32_SYSENTER_ESP,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_IA32_SYSENTER_EIP,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
// x86_64 specific msrs, we only run on x86_64 not x86
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_STAR,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_CSTAR,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_KERNEL_GS_BASE,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_SYSCALL_MASK,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_LSTAR,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
// end of x86_64 specific code
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_IA32_TSC,
|
||||
data: 0x0,
|
||||
..Default::default()
|
||||
});
|
||||
entries.push(kvm_msr_entry {
|
||||
index: ::msr_index::MSR_IA32_MISC_ENABLE,
|
||||
data: ::msr_index::MSR_IA32_MISC_ENABLE_FAST_STRING as u64,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
entries
|
||||
}
|
||||
|
||||
/// Configure Model specific registers for x86
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `vcpu` - Structure for the vcpu that holds the vcpu fd.
|
||||
pub fn setup_msrs(vcpu: &kvm::Vcpu) -> Result<()> {
|
||||
let entry_vec = create_msr_entries();
|
||||
let vec_size_bytes = mem::size_of::<kvm_msrs>() +
|
||||
(entry_vec.len() * mem::size_of::<kvm_msr_entry>());
|
||||
let vec: Vec<u8> = Vec::with_capacity(vec_size_bytes);
|
||||
let mut msrs: &mut kvm_msrs = unsafe {
|
||||
// Converting the vector's memory to a struct is unsafe. Carefully using the read-only
|
||||
// vector to size and set the members ensures no out-of-bounds erros below.
|
||||
&mut *(vec.as_ptr() as *mut kvm_msrs)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
// Mapping the unsized array to a slice is unsafe becase the length isn't known. Providing
|
||||
// the length used to create the struct guarantees the entire slice is valid.
|
||||
let entries: &mut [kvm_msr_entry] = msrs.entries.as_mut_slice(entry_vec.len());
|
||||
entries.copy_from_slice(&entry_vec);
|
||||
}
|
||||
msrs.nmsrs = entry_vec.len() as u32;
|
||||
|
||||
vcpu.set_msrs(&msrs)
|
||||
.map_err(|e| Error::MsrIoctlFailed(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configure FPU registers for x86
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `vcpu` - Structure for the vcpu that holds the vcpu fd.
|
||||
pub fn setup_fpu(vcpu: &kvm::Vcpu) -> Result<()> {
|
||||
let fpu: kvm_fpu = kvm_fpu {
|
||||
fcw: 0x37f,
|
||||
mxcsr: 0x1f80,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
vcpu.set_fpu(&fpu)
|
||||
.map_err(|e| Error::FpuIoctlFailed(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configure base registers for x86
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `vcpu` - Structure for the vcpu that holds the vcpu fd.
|
||||
/// * `boot_ip` - Starting instruction pointer.
|
||||
/// * `boot_sp` - Starting stack pointer.
|
||||
/// * `boot_si` - Must point to zero page address per Linux ABI.
|
||||
pub fn setup_regs(vcpu: &kvm::Vcpu, boot_ip: u64, boot_sp: u64, boot_si: u64) -> Result<()> {
|
||||
let regs: kvm_regs = kvm_regs {
|
||||
rflags: 0x0000000000000002u64,
|
||||
rip: boot_ip,
|
||||
rsp: boot_sp,
|
||||
rbp: boot_sp,
|
||||
rsi: boot_si,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
vcpu.set_regs(®s)
|
||||
.map_err(|e| Error::SettingRegistersIoctl(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const X86_CR0_PE: u64 = 0x1;
|
||||
const X86_CR0_PG: u64 = 0x80000000;
|
||||
const X86_CR4_PAE: u64 = 0x20;
|
||||
|
||||
const EFER_LME: u64 = 0x100;
|
||||
|
||||
const BOOT_GDT_OFFSET: usize = 0x500;
|
||||
const BOOT_IDT_OFFSET: usize = 0x520;
|
||||
|
||||
const BOOT_GDT_MAX: usize = 4;
|
||||
|
||||
fn write_gdt_table(table: &[u64; BOOT_GDT_MAX], out: &mut [u8]) {
|
||||
let mut writer = Cursor::new(&mut out[BOOT_GDT_OFFSET..
|
||||
(BOOT_GDT_OFFSET + mem::size_of_val(table))]);
|
||||
for entry in table.iter() {
|
||||
writer.write_u64::<LittleEndian>(*entry).unwrap(); // Can't fail if the above slice worked.
|
||||
}
|
||||
}
|
||||
|
||||
fn write_idt_value(val: u64, out: &mut [u8]) {
|
||||
let mut writer = Cursor::new(&mut out[BOOT_IDT_OFFSET..
|
||||
(BOOT_IDT_OFFSET + mem::size_of::<u64>())]);
|
||||
writer.write_u64::<LittleEndian>(val).unwrap(); // Can't fail if the above slice worked.
|
||||
}
|
||||
|
||||
fn configure_segments_and_sregs(mem: &mut [u8], sregs: &mut kvm_sregs) {
|
||||
let gdt_table: [u64; BOOT_GDT_MAX as usize] = [
|
||||
gdt::gdt_entry(0, 0, 0), // NULL
|
||||
gdt::gdt_entry(0xa09b, 0, 0xfffff), // CODE
|
||||
gdt::gdt_entry(0xc093, 0, 0xfffff), // DATA
|
||||
gdt::gdt_entry(0x808b, 0, 0xfffff), // TSS
|
||||
];
|
||||
|
||||
let code_seg = gdt::kvm_segment_from_gdt(gdt_table[1], 1);
|
||||
let data_seg = gdt::kvm_segment_from_gdt(gdt_table[2], 2);
|
||||
let tss_seg = gdt::kvm_segment_from_gdt(gdt_table[3], 3);
|
||||
|
||||
// Write segments
|
||||
write_gdt_table(&gdt_table, mem);
|
||||
sregs.gdt.base = BOOT_GDT_OFFSET as u64;
|
||||
sregs.gdt.limit = mem::size_of_val(&gdt_table) as u16 - 1;
|
||||
|
||||
write_idt_value(0, mem);
|
||||
sregs.idt.base = BOOT_IDT_OFFSET as u64;
|
||||
sregs.idt.limit = mem::size_of::<u64>() as u16 - 1;
|
||||
|
||||
sregs.cs = code_seg;
|
||||
sregs.ds = data_seg;
|
||||
sregs.es = data_seg;
|
||||
sregs.fs = data_seg;
|
||||
sregs.gs = data_seg;
|
||||
sregs.ss = data_seg;
|
||||
sregs.tr = tss_seg;
|
||||
|
||||
/* 64-bit protected mode */
|
||||
sregs.cr0 |= X86_CR0_PE;
|
||||
sregs.efer |= EFER_LME;
|
||||
}
|
||||
|
||||
fn setup_page_tables(mem: &mut [u8], sregs: &mut kvm_sregs) {
|
||||
// Puts PML4 right after zero page but aligned to 4k.
|
||||
const BOOT_PML4_OFFSET: usize = 0x9000;
|
||||
const BOOT_PDPTE_OFFSET: usize = 0xa000;
|
||||
const TABLE_LEN: usize = 4096;
|
||||
|
||||
{
|
||||
let out_slice = &mut mem[BOOT_PML4_OFFSET..(BOOT_PML4_OFFSET + TABLE_LEN)];
|
||||
for v in out_slice.iter_mut() {
|
||||
*v = 0;
|
||||
}
|
||||
let mut writer = Cursor::new(out_slice);
|
||||
// write_u64 Can't fail if the above slice works.
|
||||
writer
|
||||
.write_u64::<LittleEndian>(BOOT_PDPTE_OFFSET as u64 | 3)
|
||||
.unwrap();
|
||||
}
|
||||
{
|
||||
let out_slice = &mut mem[BOOT_PDPTE_OFFSET..(BOOT_PDPTE_OFFSET + TABLE_LEN)];
|
||||
for v in out_slice.iter_mut() {
|
||||
*v = 0;
|
||||
}
|
||||
let mut writer = Cursor::new(out_slice);
|
||||
writer.write_u64::<LittleEndian>(0x83).unwrap(); // Can't fail if the slice works.
|
||||
}
|
||||
sregs.cr3 = BOOT_PML4_OFFSET as u64;
|
||||
sregs.cr4 |= X86_CR4_PAE;
|
||||
sregs.cr0 |= X86_CR0_PG;
|
||||
}
|
||||
|
||||
/// Configures the segment registers and system page tables for a given CPU.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `guest_mem` - The memory that will be passed to the guest.
|
||||
/// * `vcpu_fd` - The FD returned from the KVM_CREATE_VCPU ioctl.
|
||||
pub fn setup_sregs(mem: &mut [u8], vcpu: &kvm::Vcpu) -> Result<()> {
|
||||
let mut sregs: kvm_sregs = vcpu.get_sregs()
|
||||
.map_err(|e| Error::SRegsIoctlFailed(e))?;
|
||||
|
||||
configure_segments_and_sregs(mem, &mut sregs);
|
||||
setup_page_tables(mem, &mut sregs); // TODO(dgreid) - Can this be done once per system instead?
|
||||
|
||||
vcpu.set_sregs(&sregs)
|
||||
.map_err(|e| Error::SRegsIoctlFailed(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::io::Cursor;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn segments_and_sregs() {
|
||||
let mut sregs: kvm_sregs = Default::default();
|
||||
let mut mem_vec: Vec<u8> = Vec::with_capacity(0x10000);
|
||||
unsafe {
|
||||
mem_vec.set_len(0x10000);
|
||||
}
|
||||
configure_segments_and_sregs(mem_vec.as_mut_slice(), &mut sregs);
|
||||
let mut reader = Cursor::new(&mem_vec.as_slice()[BOOT_GDT_OFFSET..]);
|
||||
assert_eq!(0, reader.read_u64::<LittleEndian>().unwrap());
|
||||
assert_eq!(0xaf9b000000ffff, reader.read_u64::<LittleEndian>().unwrap());
|
||||
assert_eq!(0xcf93000000ffff, reader.read_u64::<LittleEndian>().unwrap());
|
||||
assert_eq!(0x8f8b000000ffff, reader.read_u64::<LittleEndian>().unwrap());
|
||||
let mut reader = Cursor::new(&mem_vec.as_slice()[BOOT_IDT_OFFSET..]);
|
||||
assert_eq!(0, reader.read_u64::<LittleEndian>().unwrap());
|
||||
assert_eq!(0, sregs.cs.base);
|
||||
assert_eq!(0xfffff, sregs.ds.limit);
|
||||
assert_eq!(0x10, sregs.es.selector);
|
||||
assert_eq!(1, sregs.fs.present);
|
||||
assert_eq!(1, sregs.gs.g);
|
||||
assert_eq!(0, sregs.ss.avl);
|
||||
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!(EFER_LME, sregs.efer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn page_tables() {
|
||||
let mut sregs: kvm_sregs = Default::default();
|
||||
let mut mem_vec: Vec<u8> = Vec::with_capacity(0x10000);
|
||||
unsafe {
|
||||
mem_vec.set_len(0x10000);
|
||||
}
|
||||
setup_page_tables(mem_vec.as_mut_slice(), &mut sregs);
|
||||
let mut reader = Cursor::new(&mem_vec.as_slice()[0x9000..]);
|
||||
assert_eq!(0xa003, reader.read_u64::<LittleEndian>().unwrap());
|
||||
let mut reader = Cursor::new(&mem_vec.as_slice()[0xa000..]);
|
||||
assert_eq!(0x83, reader.read_u64::<LittleEndian>().unwrap());
|
||||
assert_eq!(0x9000, sregs.cr3);
|
||||
assert_eq!(X86_CR4_PAE, sregs.cr4);
|
||||
assert_eq!(X86_CR0_PG, sregs.cr0);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue