Skip to content

Resolve #51, use new asm! macro #115

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

Merged
merged 16 commits into from
Jan 28, 2021
Merged
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
13 changes: 7 additions & 6 deletions mythril/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ pub fn check_vm_insruction(rflags: u64, error: String) -> Result<()> {
} else if rflags.contains(RFlags::FLAGS_ZF) {
let errno = unsafe {
let value: u64;
llvm_asm!("vmread %rax, %rdx;"
: "={rdx}"(value)
: "{rax}"(vmcs::VmcsField::VmInstructionError as u64)
: "rflags"
: "volatile");
asm!(
"vmread rdx, rax",
in("rax") vmcs::VmcsField::VmInstructionError as u64,
out("rdx") value,
options(nostack)
);
value
};
let vm_error = VmInstructionError::try_from(errno)
Expand Down Expand Up @@ -137,7 +138,7 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
loop {
unsafe {
// Try to at least keep CPU from running at 100%
llvm_asm!("hlt" :::: "volatile");
asm!("hlt", options(nostack, nomem));
}
}
}
Expand Down
85 changes: 46 additions & 39 deletions mythril/src/interrupt/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,43 +79,47 @@ pub struct FaultState {
}

macro_rules! push_regs {
() => (llvm_asm!(
"push rax
push rbx
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15"
: : : : "intel", "volatile"
));
() => {
#[rustfmt::skip]
asm!(
"push rax",
"push rbx",
"push rcx",
"push rdx",
"push rdi",
"push rsi",
"push r8",
"push r9",
"push r10",
"push r11",
"push r12",
"push r13",
"push r14",
"push r15",
)
};
}

macro_rules! pop_regs {
() => (llvm_asm!(
"pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rbx
pop rax"
: : : : "intel", "volatile"
));
() => {
#[rustfmt::skip]
asm!(
"pop r15",
"pop r14",
"pop r13",
"pop r12",
"pop r11",
"pop r10",
"pop r9",
"pop r8",
"pop rsi",
"pop rdi",
"pop rdx",
"pop rcx",
"pop rbx",
"pop rax",
)
};
}

macro_rules! interrupt_fn_impl {
Expand All @@ -129,7 +133,11 @@ macro_rules! interrupt_fn_impl {
push_regs!();

let rbp: usize;
llvm_asm!("" : "={rbp}"(rbp) : : : "volatile");
asm!(
"mov {}, rbp",
out(reg) rbp,
options(nomem, nostack)
);

// Plus usize to skip the old rpb value pushed in the preamble
let stack = &*( (rbp + core::mem::size_of::<usize>()) as *const $type);
Expand All @@ -139,10 +147,9 @@ macro_rules! interrupt_fn_impl {

// Remove this stack frame before the iretq. This should work
// whether the above 'rbp' local variable is stack allocated or not.
llvm_asm!("mov rsp, rbp
pop rbp
iretq"
: : : : "intel", "volatile");
asm!("mov rsp, rbp",
"pop rbp",
"iretq");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions mythril/src/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ pub mod gsi {
}

pub unsafe fn enable_interrupts() {
llvm_asm!("sti" :::: "volatile");
asm!("sti", options(nomem, nostack));
}

pub unsafe fn disable_interrupts() {
llvm_asm!("cli" :::: "volatile");
asm!("cli", options(nomem, nostack));
}
2 changes: 1 addition & 1 deletion mythril/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![cfg_attr(not(std), no_std)]
#![feature(llvm_asm)]
#![feature(asm)]
#![feature(never_type)]
#![feature(const_fn)]
#![feature(get_mut_unchecked)]
Expand Down
2 changes: 1 addition & 1 deletion mythril/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ pub mod ro_after_init;
#[inline(always)]
pub fn relax_cpu() {
unsafe {
llvm_asm!("rep; nop" ::: "memory");
asm!("rep", "nop");
}
}
13 changes: 8 additions & 5 deletions mythril/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,14 @@ pub unsafe fn raw_write_console(s: impl AsRef<str>) {
let len = s.as_ref().len();
let ptr = s.as_ref().as_ptr();

llvm_asm!("cld; rep outsb"
:
:"{rdx}"(0x3f8), "{rcx}"(len as u64), "{rsi}"(ptr as u64)
: "rflags", "rsi"
: "volatile");
asm!(
"cld",
"rep outsb",
in("rdx") 0x3f8,
in("rcx") len as u64,
inout("rsi") ptr as u64 => _,
options(nostack)
);
}

pub struct VgaWriter {
Expand Down
20 changes: 10 additions & 10 deletions mythril/src/registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ impl IdtrBase {
limit: 0,
base_addr: 0,
};
llvm_asm!("sidt ($0)"
:
: "r"(&mut info)
: "memory"
: "volatile");
asm!(
"sidt fword ptr [{0}]",
in(reg) &mut info,
options(nostack)
);
info.base_addr
}
}
Expand All @@ -35,11 +35,11 @@ impl GdtrBase {
pub fn read() -> u64 {
unsafe {
let mut info = GdtInfo { size: 0, offset: 0 };
llvm_asm!("sgdtq ($0)"
:
: "r"(&mut info)
: "memory"
: "volatile");
asm!(
"sgdt fword ptr [{0}]",
in(reg) &mut info,
options(nostack)
);
info.offset
}
}
Expand Down
46 changes: 27 additions & 19 deletions mythril/src/vmcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,14 @@ fn vmcs_write_with_fixed(
fn vmcs_write(field: VmcsField, value: u64) -> Result<()> {
let rflags = unsafe {
let rflags: u64;
llvm_asm!("vmwrite %rdx, %rax; pushfq; popq $0"
: "=r"(rflags)
: "{rdx}"(value), "{rax}"(field as u64)
: "rflags"
: "volatile");
asm!(
"vmwrite rax, rdx",
"pushf",
"pop {}",
lateout(reg) rflags,
in("rdx") value,
in("rax") field as u64,
);
rflags
};

Expand All @@ -343,11 +346,11 @@ fn vmcs_write(field: VmcsField, value: u64) -> Result<()> {
fn vmcs_read(field: VmcsField) -> Result<u64> {
let value = unsafe {
let value: u64;
llvm_asm!("vmreadq %rdx, %rax"
: "={rax}"(value)
: "{rdx}"(field as u64)
: "rflags"
: "volatile");
asm!(
"vmread rax, rdx",
out("rax") value,
in("rdx") field as u64
);
value
};

Expand All @@ -363,10 +366,13 @@ fn vmcs_activate(vmcs: &mut Vmcs, _vmx: &vmx::Vmx) -> Result<()> {
}
let rflags = unsafe {
let rflags: u64;
llvm_asm!("vmptrld $1; pushfq; popq $0"
: "=r"(rflags)
: "m"(vmcs_region_addr)
: "rflags");
asm!(
"vmptrld [{}]",
"pushf",
"pop {}",
in(reg) &vmcs_region_addr,
lateout(reg) rflags
);
rflags
};

Expand All @@ -376,11 +382,13 @@ fn vmcs_activate(vmcs: &mut Vmcs, _vmx: &vmx::Vmx) -> Result<()> {
fn vmcs_clear(vmcs_page: &mut Raw4kPage) -> Result<()> {
let rflags = unsafe {
let rflags: u64;
llvm_asm!("vmclear $1; pushfq; popq $0"
: "=r"(rflags)
: "m"(vmcs_page as *const _ as u64)
: "rflags"
: "volatile");
asm!(
"vmclear [{}]",
"pushf",
"pop {}",
in(reg) &(vmcs_page as *const _ as u64),
lateout(reg) rflags
);
rflags
};
error::check_vm_insruction(rflags, "Failed to clear VMCS".into())
Expand Down
67 changes: 45 additions & 22 deletions mythril/src/vmx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,24 @@ impl Vmx {

unsafe {
// Enable NE in CR0, This is fixed bit in VMX CR0
llvm_asm!("movq %cr0, %rax; orq %rdx, %rax; movq %rax, %cr0;"
:
: "{rdx}"(0x20)
: "rax");
asm!(
"mov rax, cr0",
"or rax, rdx",
"mov cr0, rax",
in("rdx") 0x20,
lateout("rax") _,
options(nomem, nostack)
);

// Enable vmx in CR4
llvm_asm!("movq %cr4, %rax; orq %rdx, %rax; movq %rax, %cr4;"
:
: "{rdx}"(VMX_ENABLE_FLAG)
: "rax");
asm!(
"mov rax, cr4",
"or rax, rdx",
"mov cr4, rax",
in("rdx") VMX_ENABLE_FLAG,
lateout("rax") _,
options(nomem, nostack)
);
}

let revision_id = Self::revision();
Expand All @@ -45,10 +53,13 @@ impl Vmx {

let rflags = unsafe {
let rflags: u64;
llvm_asm!("vmxon $1; pushfq; popq $0"
: "=r"(rflags)
: "m"(vmxon_region_addr)
: "rflags");
asm!(
"vmxon [{}]",
"pushf",
"pop {}",
in(reg) &vmxon_region_addr,
lateout(reg) rflags,
);
rflags
};

Expand All @@ -63,10 +74,12 @@ impl Vmx {
// was originally activated from
let rflags = unsafe {
let rflags: u64;
llvm_asm!("vmxoff; pushfq; popq $0"
: "=r"(rflags)
:
: "rflags");
asm!(
"vmxoff",
"pushf",
"pop {}",
lateout(reg) rflags,
);
rflags
};

Expand All @@ -85,9 +98,14 @@ impl Vmx {

let rflags = unsafe {
let rflags: u64;
llvm_asm!("invept $1, $2; pushfq; popq $0"
: "=r"(rflags)
: "m"(val), "r"(t));
asm!(
"invept {}, [{}]",
"pushfq",
"pop {}",
in(reg) t,
in(reg) &val,
lateout(reg) rflags
);
rflags
};
error::check_vm_insruction(rflags, "Failed to execute invept".into())
Expand All @@ -107,9 +125,14 @@ impl Vmx {

let rflags = unsafe {
let rflags: u64;
llvm_asm!("invvpid $1, $2; pushfq; popq $0"
: "=r"(rflags)
: "m"(val), "r"(t));
asm!(
"invvpid {}, [{}]",
"pushfq",
"pop {}",
in(reg) t,
in(reg) &val,
lateout(reg) rflags
);
rflags
};
error::check_vm_insruction(rflags, "Failed to execute invvpid".into())
Expand Down