Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Windows Hypervisor Platform APIs #977

Open
wants to merge 8 commits into
base: 0.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ winefs = []
winevt = []
wingdi = []
winhttp = []
winhvemulation = []
winhvplatform = []
winhvplatformdefs = []
wininet = []
winineti = []
winioctl = []
Expand Down
54 changes: 51 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ const DATA: &'static [(&'static str, &'static [&'static str], &'static [&'static
("winevt", &["basetsd", "guiddef", "minwinbase", "minwindef", "vcruntime", "winnt"], &["wevtapi"]),
("wingdi", &["basetsd", "minwindef", "windef", "winnt"], &["gdi32", "msimg32", "opengl32", "winspool"]),
("winhttp", &["basetsd", "minwinbase", "minwindef", "winnt"], &["winhttp"]),
("winhvemulation", &["basetsd", "minwindef", "ntdef", "winhvplatformdefs"], &["winhvemulation"]),
("winhvplatform", &["basetsd", "minwindef", "ntdef", "winhvplatformdefs"], &["winhvplatform"]),
("winhvplatformdefs", &["basetsd", "minwindef"], &[]),
("wininet", &["basetsd", "minwinbase", "minwindef", "ntdef", "windef", "winineti", "winnt"], &["wininet"]),
("winineti", &["minwindef"], &[]),
("winioctl", &["basetsd", "devpropdef", "guiddef", "minwindef", "winnt"], &[]),
Expand Down Expand Up @@ -416,7 +419,7 @@ struct Header {
dependencies: &'static [&'static str],
libraries: &'static [&'static str],
}
struct Graph(HashMap<&'static str, Header>);
struct Graph(HashMap<&'static str, Header>, bool);
impl Graph {
fn generate() -> Graph {
Graph(DATA.iter().map(|&(name, dependencies, libraries)| {
Expand All @@ -427,7 +430,7 @@ impl Graph {
libraries: libraries,
};
(name, header)
}).collect())
}).collect(), probe_align16())
}
fn identify_required(&mut self) {
for (name, header) in &mut self.0 {
Expand All @@ -439,7 +442,12 @@ impl Graph {
}
fn check_everything(&self) {
if let Ok(_) = var("CARGO_FEATURE_EVERYTHING") {
for (_, header) in &self.0 {
for (name, header) in &self.0 {
if name == &"winhvplatform" || name == &"winhvplatformdefs" || name == &"winhvemulation"{
if !self.1{
continue;
}
}
header.included.set(true);
}
}
Expand All @@ -463,6 +471,13 @@ impl Graph {
}
fn emit_features(&self) {
for (name, header) in &self.0 {
if header.included.get(){
if name == &"winhvplatform" || name == &"winhvplatformdefs" || name == &"winhvemulation"{
if !self.1{
panic!("WinHV requires #[repr(C, align(16))] which is incompatible with this rustc version.");
}
}
}
if header.included.get() && !header.required {
println!("cargo:rustc-cfg=feature=\"{}\"", name);
}
Expand All @@ -484,6 +499,13 @@ impl Graph {
},
_ => true,
});
libs.retain(|&&lib| match &*var("TARGET").unwrap() {
"i586-pc-windows-msvc" | "i686-pc-windows-msvc" | "aarch64-pc-windows-msvc" | "i586-pc-windows-gnu" | "i686-pc-windows-gnu" | "aarch64-pc-windows-gnu" => {
if lib == "winhvemulation" || lib == "winhvplatform" { false }
else { true }
},
_ => true,
});
let prefix = library_prefix();
let kind = library_kind();
for lib in libs {
Expand All @@ -509,12 +531,38 @@ fn library_kind() -> &'static str {
}
fn try_everything() {
let mut graph = Graph::generate();

graph.identify_required();
graph.check_everything();
graph.resolve_dependencies();
graph.emit_features();
graph.emit_libraries();
}
fn probe<T: AsRef<[u8]>>(code: T)->bool{
use std::process::{Command, Stdio};
use std::io::Write;
let mut command = Command::new(&var("RUSTC").unwrap_or_else(|_| "rustc".into()));
let mut child=command.arg("--crate-name")
.arg("rustc_probe")
.arg("--crate-type=lib")
.arg("--out-dir")
.arg(&var("OUT_DIR").unwrap())
.arg("--emit=llvm-ir")
.arg("-").stdin(Stdio::piped()).spawn().unwrap();
let mut stdin = child.stdin.take().unwrap();
stdin.write_all(code.as_ref()).unwrap();
drop(stdin);
let status=child.wait().unwrap();
return status.success();
}
fn probe_align16()->bool{
let code = "
#[repr(C, align(16))]
struct Aligned(u64,u64);
";
let ret=probe(&code);
ret
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=WINAPI_NO_BUNDLED_LIBRARIES");
Expand Down
11 changes: 11 additions & 0 deletions src/shared/winerror.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6148,3 +6148,14 @@ pub const WININET_E_NOT_REDIRECTED: HRESULT = 0x80072F80;
pub const WININET_E_COOKIE_NEEDS_CONFIRMATION: HRESULT = 0x80072F81;
pub const WININET_E_COOKIE_DECLINED: HRESULT = 0x80072F82;
pub const WININET_E_REDIRECT_NEEDS_CONFIRMATION: HRESULT = 0x80072F88;
pub const WHV_E_UNKNOWN_CAPABILITY: HRESULT = 0x80370300;
pub const WHV_E_INSUFFICIENT_BUFFER: HRESULT = 0x80370301;
pub const WHV_E_UNKNOWN_PROPERTY: HRESULT = 0x80370302;
pub const WHV_E_UNSUPPORTED_HYPERVISOR_CONFIG: HRESULT = 0x80370303;
pub const WHV_E_INVALID_PARTITION_CONFIG: HRESULT = 0x80370304;
pub const WHV_E_GPA_RANGE_NOT_FOUND: HRESULT = 0x80370305;
pub const WHV_E_VP_ALREADY_EXISTS: HRESULT = 0x80370306;
pub const WHV_E_VP_DOES_NOT_EXIST: HRESULT = 0x80370307;
pub const WHV_E_INVALID_VP_STATE: HRESULT = 0x80370308;
pub const WHV_E_INVALID_VP_REGISTER_NAME: HRESULT = 0x80370309;
pub const WHV_E_UNSUPPORTED_PROCESSOR_CONFIG: HRESULT = 0x80370310;
3 changes: 3 additions & 0 deletions src/um/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ pub mod gl;
#[cfg(feature = "winevt")] pub mod winevt;
#[cfg(feature = "wingdi")] pub mod wingdi;
#[cfg(feature = "winhttp")] pub mod winhttp;
#[cfg(feature = "winhvemulation")] pub mod winhvemulation;
#[cfg(feature = "winhvplatform")] pub mod winhvplatform;
#[cfg(feature = "winhvplatformdefs")] pub mod winhvplatformdefs;
#[cfg(feature = "wininet")] pub mod wininet;
#[cfg(feature = "winineti")] pub mod winineti;
#[cfg(feature = "winioctl")] pub mod winioctl;
Expand Down
100 changes: 100 additions & 0 deletions src/um/winhvemulation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use shared::basetsd::{UINT16, UINT32, UINT8};
use shared::minwindef::LPVOID;
use shared::ntdef::{BOOLEAN, HRESULT};
use um::winhvplatformdefs::*;
STRUCT!{struct WHV_EMULATOR_STATUS {
AsUINT32: UINT32,
}}
BITFIELD!{WHV_EMULATOR_STATUS AsUINT32: UINT32 [
EmulationSuccessful set_EmulationSuccessful [0..1],
InternalEmulationFailure set_InternalEmulationFailure [1..2],
IoPortCallbackFailed set_IoPortCallbackFailed [2..3],
MemoryCallbackFailed set_MemoryCallbackFailed [3..4],
TranslateGvaPageCallbackFailed set_TranslateGvaPageCallbackFailed [4..5],
TranslateGvaPageCallbackGpaIsNotAligned
set_TranslateGvaPageCallbackGpaIsNotAligned [5..6],
GetVirtualProcessorRegistersCallbackFailed
set_GetVirtualProcessorRegistersCallbackFailed [6..7],
SetVirtualProcessorRegistersCallbackFailed
set_SetVirtualProcessorRegistersCallbackFailed [7..8],
InterruptCausedIntercept set_InterruptCausedIntercept [8..9],
GuestCannotBeFaultedGuestCannotBeFaulted
set_GuestCannotBeFaultedGuestCannotBeFaulted [9..10],
Reserved set_Reserved [10..32],
]}
STRUCT!{struct WHV_EMULATOR_MEMORY_ACCESS_INFO{
GpaAddress: WHV_GUEST_PHYSICAL_ADDRESS,
Direction: UINT8,
AccessSize: UINT8,
Data: [UINT8; 5],
}}
STRUCT!{struct WHV_EMULATOR_IO_ACCESS_INFO{
Direction: UINT8,
Port: UINT16,
AccessSize: UINT16,
Data: UINT32,
}}
FN!{stdcall WHV_EMULATOR_IO_PORT_CALLBACK(
Context: LPVOID,
IOAccess: *mut WHV_EMULATOR_IO_ACCESS_INFO,
) -> HRESULT}
FN!{stdcall WHV_EMULATOR_MEMORY_CALLBACK(
Context: LPVOID,
MemoryAccess: *mut WHV_EMULATOR_MEMORY_ACCESS_INFO,
) -> HRESULT}
FN!{stdcall WHV_EMULATOR_GET_VIRTUAL_PROCESSOR_REGISTERS_CALLBACK(
Context: LPVOID,
RegisterNames: *const WHV_REGISTER_NAME,
RegisterCount: UINT32,
RegisterValues: *mut WHV_REGISTER_VALUE,
) -> HRESULT}
FN!{stdcall WHV_EMULATOR_SET_VIRTUAL_PROCESSOR_REGISTERS_CALLBACK(
Context: LPVOID,
RegisterNames: *const WHV_REGISTER_NAME,
RegisterCount: UINT32,
RegisterValues: *const WHV_REGISTER_VALUE,
) -> HRESULT}
FN!{stdcall WHV_EMULATOR_TRANSLATE_GVA_PAGE_CALLBACK(
Context: LPVOID,
Gva: WHV_GUEST_VIRTUAL_ADDRESS,
TranslateFlags: WHV_TRANSLATE_GVA_FLAGS,
TranslationResult: *mut WHV_TRANSLATE_GVA_RESULT_CODE,
Gpa: *mut WHV_GUEST_PHYSICAL_ADDRESS,
) -> HRESULT}
STRUCT!{struct WHV_EMULATOR_CALLBACKS{
Size: UINT32,
Reserved: UINT32,
WHvEmulatorIoPortCallback: WHV_EMULATOR_IO_PORT_CALLBACK,
WHvEmulatorMemoryCallback: WHV_EMULATOR_MEMORY_CALLBACK,
WHvEmulatorGetVirtualProcessorRegisters: WHV_EMULATOR_GET_VIRTUAL_PROCESSOR_REGISTERS_CALLBACK,
WHvEmulatorSetVirtualProcessorRegisters: WHV_EMULATOR_SET_VIRTUAL_PROCESSOR_REGISTERS_CALLBACK,
WHvEmulatorTranslateGvaPage: WHV_EMULATOR_TRANSLATE_GVA_PAGE_CALLBACK,
}}
pub type WHV_EMULATOR_HANDLE = LPVOID;
extern "system" {
pub fn WHvEmulatorCreateEmulator(
Callbacks: *const WHV_EMULATOR_CALLBACKS,
Emulator: *mut WHV_EMULATOR_HANDLE,
)->HRESULT;
pub fn WHvEmulatorDestroyEmulator(
Emulator: *mut WHV_EMULATOR_HANDLE,
)->HRESULT;
pub fn WHvEmulatorTryIoEmulation(
Emulator: *mut WHV_EMULATOR_HANDLE,
Context: LPVOID,
VpContext: *const WHV_VP_EXIT_CONTEXT,
IoInstructionContext: *const WHV_X64_IO_PORT_ACCESS_CONTEXT,
EmulatorReturnStatus: *mut WHV_EMULATOR_STATUS,
)->HRESULT;
pub fn WHvEmulatorTryMmioEmulation(
Emulator: WHV_EMULATOR_HANDLE,
Context: LPVOID,
VpContext: *const WHV_VP_EXIT_CONTEXT,
MmioInstructionContext: *const WHV_MEMORY_ACCESS_CONTEXT,
EmulatorReturnStatus: *mut WHV_EMULATOR_STATUS,
)->HRESULT;
pub fn IsWHvEmulatorCreateEmulatorPresent()->BOOLEAN;
pub fn IsWHvEmulatorDestroyEmulatorPresent()->BOOLEAN;
pub fn IsWHvEmulatorTryIoEmulationPresent()->BOOLEAN;
pub fn IsWHvEmulatorTryMmioEmulationPresent()->BOOLEAN;
}
Loading