x86_64: use __cpuid intrinsic

Use the Rust __cpuid and __cpuid_count intrinsics to replace the C
implementation in host_cpuid.c.

These are defined in core, but they are also re-exported in std, despite
being undocumented there due to technical reasons:
https://github.com/rust-lang/rust/pull/57808#issuecomment-457390549

Use the std version for consistency (we don't currently use anything
from core anywhere else in crosvm).

BUG=None
TEST=cargo test -p x86_64
TEST=Boot crosvm on x86_64

Change-Id: Ic7a1094d1b804304a2944f8ee1fe55c5e2db23e9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2067159
Reviewed-by: Zach Reizner <zachr@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Daniel Verkamp 2020-02-20 12:13:09 -08:00 committed by Commit Bot
parent f84c2298e9
commit 0275efb3a0
5 changed files with 15 additions and 78 deletions

1
Cargo.lock generated
View file

@ -639,7 +639,6 @@ version = "0.1.0"
dependencies = [
"arch 0.1.0",
"assertions 0.1.0",
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"data_model 0.1.0",
"devices 0.1.0",
"io_jail 0.1.0",

View file

@ -3,7 +3,6 @@ name = "x86_64"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
build = "build.rs"
[dependencies]
arch = { path = "../arch" }
@ -20,6 +19,3 @@ remain = "*"
resources = { path = "../resources" }
sync = { path = "../sync" }
sys_util = { path = "../sys_util" }
[build-dependencies]
cc = "=1.0.25"

View file

@ -1,7 +0,0 @@
// Copyright 2018 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.
fn main() {
cc::Build::new().file("host_cpuid.c").compile("host_cpuid");
}

View file

@ -1,11 +0,0 @@
// Copyright 2018 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.
#include <stdint.h>
void host_cpuid(uint32_t func, uint32_t func2, uint32_t *pEax,
uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx) {
asm volatile("cpuid" : "=a"(*pEax), "=b"(*pEbx), "=c"(*pEcx), "=d"(*pEdx) :
"0"(func), "2"(func2) : "cc");
}

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::arch::x86_64::{__cpuid, __cpuid_count};
use std::fmt::{self, Display};
use std::result;
@ -28,19 +29,6 @@ impl Display for Error {
}
}
// This function is implemented in C because stable rustc does not
// support inline assembly.
extern "C" {
fn host_cpuid(
func: u32,
func2: u32,
rEax: *mut u32,
rEbx: *mut u32,
rEcx: *mut u32,
rEdx: *mut u32,
) -> ();
}
// 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.
@ -77,25 +65,19 @@ fn filter_cpuid(
}
}
2 | 0x80000005 | 0x80000006 => unsafe {
host_cpuid(
entry.function,
0,
&mut entry.eax as *mut u32,
&mut entry.ebx as *mut u32,
&mut entry.ecx as *mut u32,
&mut entry.edx as *mut u32,
);
let result = __cpuid(entry.function);
entry.eax = result.eax;
entry.ebx = result.ebx;
entry.ecx = result.ecx;
entry.edx = result.edx;
},
4 => {
unsafe {
host_cpuid(
entry.function,
entry.index,
&mut entry.eax as *mut u32,
&mut entry.ebx as *mut u32,
&mut entry.ecx as *mut u32,
&mut entry.edx as *mut u32,
);
let result = __cpuid_count(entry.function, entry.index);
entry.eax = result.eax;
entry.ebx = result.ebx;
entry.ecx = result.ecx;
entry.edx = result.edx;
}
entry.eax &= !0xFC000000;
}
@ -132,34 +114,12 @@ pub fn setup_cpuid(kvm: &kvm::Kvm, vcpu: &kvm::Vcpu, cpu_id: u64, nrcpus: u64) -
/// get host cpu max physical address bits
pub fn phy_max_address_bits() -> u32 {
let mut eax: u32 = 0;
let mut ebx: u32 = 0;
let mut ecx: u32 = 0;
let mut edx: u32 = 0;
let mut phys_bits: u32 = 36;
unsafe {
host_cpuid(
0x80000000,
0,
&mut eax as *mut u32,
&mut ebx as *mut u32,
&mut ecx as *mut u32,
&mut edx as *mut u32,
);
}
if eax >= 0x80000008 {
unsafe {
host_cpuid(
0x80000008,
0,
&mut eax as *mut u32,
&mut ebx as *mut u32,
&mut ecx as *mut u32,
&mut edx as *mut u32,
);
}
phys_bits = eax & 0xff;
let highest_ext_function = unsafe { __cpuid(0x80000000) };
if highest_ext_function.eax >= 0x80000008 {
let addr_size = unsafe { __cpuid(0x80000008) };
phys_bits = addr_size.eax & 0xff;
}
phys_bits