aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Gerd Zellweger <mail@gerdzellweger.com> 2021-04-08 02:10:35 -0700
committerGravatar Gerd Zellweger <mail@gerdzellweger.com> 2021-04-08 02:10:35 -0700
commit523296c4ecfad57ef26aabdde1446c788dbc668e (patch)
tree910cea9953116816b41c67f9550e807a2eb39cda
parente9fd841a6b89133f6afe46a8ce608af2f2e4b57e (diff)
downloadrust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.tar.gz
rust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.tar.zst
rust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.zip
Fix clippy warnings.
Diffstat (limited to '')
-rw-r--r--src/bits64/segmentation.rs30
-rw-r--r--src/bits64/sgx.rs109
-rw-r--r--src/bits64/syscall.rs28
-rw-r--r--src/bits64/vmx.rs29
-rw-r--r--src/controlregs.rs30
-rw-r--r--src/dtables.rs18
-rw-r--r--src/io.rs18
-rw-r--r--src/msr.rs6
-rw-r--r--src/random.rs41
-rw-r--r--src/segmentation.rs31
-rw-r--r--src/task.rs3
11 files changed, 296 insertions, 47 deletions
diff --git a/src/bits64/segmentation.rs b/src/bits64/segmentation.rs
index 2c83f3c..c4420d8 100644
--- a/src/bits64/segmentation.rs
+++ b/src/bits64/segmentation.rs
@@ -26,10 +26,12 @@ impl Descriptor64 {
pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) {
self.desc32.apply_builder_settings(builder);
- if let Some((base, limit)) = builder
- .base_limit { self.set_base_limit(base, limit) }
- if let Some((selector, offset)) = builder
- .selector_offset { self.set_selector_offset(selector, offset) }
+ if let Some((base, limit)) = builder.base_limit {
+ self.set_base_limit(base, limit)
+ }
+ if let Some((selector, offset)) = builder.selector_offset {
+ self.set_selector_offset(selector, offset)
+ }
}
/// Create a new segment, TSS or LDT descriptor
@@ -129,10 +131,14 @@ impl BuildDescriptor<Descriptor64> for DescriptorBuilder {
}
/// Reload code segment register.
+///
/// Note this is special since we can not directly move
/// to %cs. Instead we push the new segment selector
/// and return value on the stack and use lretq
/// to reload cs and continue at 1:.
+///
+/// # Safety
+/// Can cause a GP-fault with a bad `sel` value.
#[cfg(target_arch = "x86_64")]
pub unsafe fn load_cs(sel: SegmentSelector) {
llvm_asm!("pushq $0; \
@@ -143,6 +149,8 @@ pub unsafe fn load_cs(sel: SegmentSelector) {
}
/// Write GS Segment Base
+///
+/// # Safety
/// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set.
#[cfg(target_arch = "x86_64")]
pub unsafe fn wrgsbase(base: u64) {
@@ -150,6 +158,8 @@ pub unsafe fn wrgsbase(base: u64) {
}
/// Write FS Segment Base
+///
+/// # Safety
/// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set.
#[cfg(target_arch = "x86_64")]
pub unsafe fn wrfsbase(base: u64) {
@@ -157,6 +167,8 @@ pub unsafe fn wrfsbase(base: u64) {
}
/// Read GS Segment Base
+///
+/// # Safety
/// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set.
#[cfg(target_arch = "x86_64")]
pub unsafe fn rdgsbase() -> u64 {
@@ -166,6 +178,8 @@ pub unsafe fn rdgsbase() -> u64 {
}
/// Read FS Segment Base
+///
+/// # Safety
/// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set.
#[cfg(target_arch = "x86_64")]
pub unsafe fn rdfsbase() -> u64 {
@@ -175,6 +189,9 @@ pub unsafe fn rdfsbase() -> u64 {
}
/// "Dereferences" the fs register at offset 0.
+///
+/// # Safety
+/// fs needs to point to valid address.
#[cfg(target_arch = "x86_64")]
pub unsafe fn fs_deref() -> u64 {
let fs: u64;
@@ -183,6 +200,9 @@ pub unsafe fn fs_deref() -> u64 {
}
/// "Dereferences" the gs register at offset 0.
+///
+/// # Safety
+/// gs needs to point to valid address.
#[cfg(target_arch = "x86_64")]
pub unsafe fn gs_deref() -> u64 {
let gs: u64;
@@ -197,7 +217,7 @@ pub unsafe fn gs_deref() -> u64 {
///
/// The SWAPGS instruction is available only in 64-bit mode.
///
-/// # Unsafe
+/// # Safety
/// The SWAPGS instruction is a privileged instruction intended for use by system software.
#[cfg(target_arch = "x86_64")]
pub unsafe fn swapgs() {
diff --git a/src/bits64/sgx.rs b/src/bits64/sgx.rs
index aa302c1..3d018b3 100644
--- a/src/bits64/sgx.rs
+++ b/src/bits64/sgx.rs
@@ -45,6 +45,7 @@ unsafe fn encls4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) {
(eax, out_rbx)
}
+#[allow(clippy::upper_case_acronyms)]
enum EnclsCommand {
EADD = 0x01,
EAUG = 0x0D,
@@ -69,6 +70,9 @@ enum EnclsCommand {
/// # Arguments
/// * Address of a PAGEINFO.
/// * Address of the destination EPC page.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eadd(pageinfo: u64, epc_page: u64) {
encls!(EnclsCommand::EADD as u64, pageinfo, epc_page);
}
@@ -78,6 +82,9 @@ pub unsafe fn encls_eadd(pageinfo: u64, epc_page: u64) {
/// # Arguments
/// * Address of a SECINFO
/// * Address of the destination EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eaug(secinfo_address: u64, epc_page: u64) {
encls!(EnclsCommand::EAUG as u64, secinfo_address, epc_page);
}
@@ -86,6 +93,9 @@ pub unsafe fn encls_eaug(secinfo_address: u64, epc_page: u64) {
///
/// # Arguments
/// * Effective address of the EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eblock(epc_page: u64) -> u32 {
encls!(EnclsCommand::EBLOCK as u64, epc_page).0
}
@@ -95,6 +105,9 @@ pub unsafe fn encls_eblock(epc_page: u64) -> u32 {
/// # Arguments
/// * Address of a PAGEINFO
/// * Address of the destination SECS page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_create(pageinfo: u64, secs_page: u64) {
encls!(EnclsCommand::ECREATE as u64, pageinfo, secs_page);
}
@@ -106,6 +119,9 @@ pub unsafe fn encls_create(pageinfo: u64, secs_page: u64) {
///
/// # Arguments
/// * Address of source memory in the EPC
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_edbgrd(source_address: u64) -> u64 {
encls!(EnclsCommand::EDBGRD as u64, source_address).1
}
@@ -115,6 +131,9 @@ pub unsafe fn encls_edbgrd(source_address: u64) -> u64 {
/// # Arguments
/// * Data to be written to a debug enclave
/// * Address of Target memory in the EPC
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_edbgwr(data: u64, target_address: u64) {
encls!(EnclsCommand::EDBGWR as u64, data, target_address);
}
@@ -124,6 +143,9 @@ pub unsafe fn encls_edbgwr(data: u64, target_address: u64) {
/// # Arguments
/// * Effective address of the SECS of the data chunk
/// * Effective address of a 256-byte chunk in the EPC
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eextend(secs_chunk: u64, epc_chunk: u64) {
encls!(EnclsCommand::EEXTEND as u64, secs_chunk, epc_chunk);
}
@@ -134,6 +156,9 @@ pub unsafe fn encls_eextend(secs_chunk: u64, epc_chunk: u64) {
/// * Address of SIGSTRUCT
/// * Address of SECS
/// * Address of EINITTOKEN
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_einit(sigstruct: u64, secs: u64, einittoken: u64) -> u32 {
encls!(EnclsCommand::EINIT as u64, sigstruct, secs, einittoken).0
}
@@ -144,6 +169,9 @@ pub unsafe fn encls_einit(sigstruct: u64, secs: u64, einittoken: u64) -> u32 {
/// * Address of the PAGEINFO
/// * Address of the EPC page
/// * Address of the version-array slot
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eldb(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 {
encls!(
EnclsCommand::ELDB as u64,
@@ -160,6 +188,9 @@ pub unsafe fn encls_eldb(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -
/// * Address of the PAGEINFO
/// * Address of the EPC page
/// * Address of the version-array slot
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eldu(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 {
encls!(
EnclsCommand::ELDU as u64,
@@ -175,6 +206,9 @@ pub unsafe fn encls_eldu(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -
/// # Arguments
/// * Address of a SECINFO
/// * Address of the destination EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_emodpr(secinfo: u64, epc_page: u64) -> u32 {
encls!(EnclsCommand::EMODPR as u64, secinfo, epc_page).0
}
@@ -184,6 +218,9 @@ pub unsafe fn encls_emodpr(secinfo: u64, epc_page: u64) -> u32 {
/// # Arguments
/// * Address of a SECINFO
/// * Address of the destination EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_emodt(secinfo: u64, epc_page: u64) -> u32 {
encls!(EnclsCommand::EMODT as u64, secinfo, epc_page).0
}
@@ -193,6 +230,9 @@ pub unsafe fn encls_emodt(secinfo: u64, epc_page: u64) -> u32 {
/// # Arguments
/// * PT_VA Constant
/// * Effective address of the EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_epa(pt_va: u64, epc_page: u64) {
encls!(EnclsCommand::EPA as u64, pt_va, epc_page);
}
@@ -201,6 +241,9 @@ pub unsafe fn encls_epa(pt_va: u64, epc_page: u64) {
///
/// # Arguments
/// * Effective address of the EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_eremove(epc_page: u64) {
encls!(EnclsCommand::EREMOVE as u64, epc_page);
}
@@ -209,6 +252,9 @@ pub unsafe fn encls_eremove(epc_page: u64) {
///
/// # Arguments
/// * Pointer to the SECS of the EPC page.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_etrack(secs_pointer: u64) -> u32 {
encls!(EnclsCommand::ETRACK as u64, secs_pointer).0
}
@@ -218,6 +264,9 @@ pub unsafe fn encls_etrack(secs_pointer: u64) -> u32 {
/// # Arguments
/// * Address of the EPC page.
/// * Address of a VA slot.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn encls_ewb(pageinfo: u64, epc_page: u64, va_slot: u64) -> u32 {
encls!(EnclsCommand::EWB as u64, pageinfo, epc_page, va_slot).0
}
@@ -255,14 +304,14 @@ unsafe fn enclu4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) {
}
enum EncluCommand {
- EACCEPT = 0x05,
- EACCEPTCOPY = 0x07,
- EENTER = 0x02,
- EEXIT = 0x04,
- EGETKEY = 0x01,
- EMODEPE = 0x06,
- EREPORT = 0x00,
- ERESUME = 0x03,
+ EAccept = 0x05,
+ EAcceptCopy = 0x07,
+ EEnter = 0x02,
+ EExit = 0x04,
+ EGetKey = 0x01,
+ EModePE = 0x06,
+ EReport = 0x00,
+ EResume = 0x03,
}
/// Accept Changes to an EPC Page.
@@ -272,8 +321,11 @@ enum EncluCommand {
/// * Address of the destination EPC page.
///
/// Returns an error code.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_eaccept(secinfo: u64, epc_page: u64) -> u32 {
- enclu!(EncluCommand::EACCEPT as u64, secinfo, epc_page).0
+ enclu!(EncluCommand::EAccept as u64, secinfo, epc_page).0
}
/// Initialize a Pending Page.
@@ -284,13 +336,16 @@ pub unsafe fn enclu_eaccept(secinfo: u64, epc_page: u64) -> u32 {
/// * Address of the source EPC page.
///
/// Returns an error code.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_eacceptcopy(
secinfo: u64,
destination_epc_page: u64,
source_epc_page: u64,
) -> u32 {
enclu!(
- EncluCommand::EACCEPTCOPY as u64,
+ EncluCommand::EAcceptCopy as u64,
secinfo,
destination_epc_page,
source_epc_page
@@ -303,11 +358,14 @@ pub unsafe fn enclu_eacceptcopy(
/// # Arguments
/// * Address of a TCS.
/// * Address of AEP.
-/// * Address of IP following EENTER.
+/// * Address of IP following EEnter.
///
-/// Returns content of RBX.CSSA and Address of IP following EENTER.
+/// Returns content of RBX.CSSA and Address of IP following EEnter.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_eenter(tcs: u64, aep: u64) -> (u32, u64) {
- enclu!(EncluCommand::EENTER as u64, tcs, aep)
+ enclu!(EncluCommand::EEnter as u64, tcs, aep)
}
/// Exits an Enclave.
@@ -315,8 +373,11 @@ pub unsafe fn enclu_eenter(tcs: u64, aep: u64) -> (u32, u64) {
/// # Arguments
/// * Target address outside the enclave
/// * Address of the current AEP
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_eexit(ip: u64, aep: u64) {
- enclu!(EncluCommand::EEXIT as u64, ip, aep);
+ enclu!(EncluCommand::EExit as u64, ip, aep);
}
/// Retrieves a Cryptographic Key.
@@ -324,8 +385,11 @@ pub unsafe fn enclu_eexit(ip: u64, aep: u64) {
/// # Arguments
/// * Address to a KEYREQUEST
/// * Address of the OUTPUTDATA
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_egetkey(keyrequest: u64, outputdata: u64) {
- enclu!(EncluCommand::EGETKEY as u64, keyrequest, outputdata);
+ enclu!(EncluCommand::EGetKey as u64, keyrequest, outputdata);
}
/// Extend an EPC Page Permissions.
@@ -333,8 +397,11 @@ pub unsafe fn enclu_egetkey(keyrequest: u64, outputdata: u64) {
/// # Arguments
/// * Address of a SECINFO
/// * Address of the destination EPC page
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_emodepe(secinfo: u64, epc_page: u64) {
- enclu!(EncluCommand::EMODEPE as u64, secinfo, epc_page);
+ enclu!(EncluCommand::EModePE as u64, secinfo, epc_page);
}
/// Create a Cryptographic Report of the Enclave.
@@ -343,9 +410,12 @@ pub unsafe fn enclu_emodepe(secinfo: u64, epc_page: u64) {
/// * Address of TARGETINFO
/// * Address of REPORTDATA
/// * Address where the REPORT is written to in an OUTPUTDATA
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_ereport(targetinfo: u64, reportdata: u64, outputdata: u64) {
enclu!(
- EncluCommand::EREPORT as u64,
+ EncluCommand::EReport as u64,
targetinfo,
reportdata,
outputdata
@@ -357,6 +427,9 @@ pub unsafe fn enclu_ereport(targetinfo: u64, reportdata: u64, outputdata: u64) {
/// # Arguments
/// * Address of a TCS.
/// * Address of AEP.
+///
+/// # Safety
+/// Requires SGX support.
pub unsafe fn enclu_eresume(tcs: u64, aep: u64) {
- enclu!(EncluCommand::ERESUME as u64, tcs, aep);
+ enclu!(EncluCommand::EResume as u64, tcs, aep);
}
diff --git a/src/bits64/syscall.rs b/src/bits64/syscall.rs
index b370282..63c7c30 100644
--- a/src/bits64/syscall.rs
+++ b/src/bits64/syscall.rs
@@ -88,6 +88,10 @@ macro_rules! syscall {
};
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -97,6 +101,10 @@ pub unsafe fn syscall0(arg0: u64) -> u64 {
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -107,6 +115,10 @@ pub unsafe fn syscall1(arg0: u64, arg1: u64) -> u64 {
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -117,6 +129,10 @@ pub unsafe fn syscall2(arg0: u64, arg1: u64, arg2: u64) -> u64 {
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -127,6 +143,10 @@ pub unsafe fn syscall3(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> u64 {
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -138,6 +158,10 @@ pub unsafe fn syscall4(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) ->
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
@@ -150,6 +174,10 @@ pub unsafe fn syscall5(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, ar
ret
}
+/// Invoke a syscall.
+///
+/// # Safety
+/// Throws `#UD` if IA32_EFER.SCE = 0.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[allow(unused_mut)]
diff --git a/src/bits64/vmx.rs b/src/bits64/vmx.rs
index f64ece7..5535d36 100644
--- a/src/bits64/vmx.rs
+++ b/src/bits64/vmx.rs
@@ -11,7 +11,7 @@ use crate::vmx::{Result, VmFail};
// see https://github.com/gz/rust-x86/pull/50.
#[inline(always)]
fn vmx_capture_status() -> Result<()> {
- let flags = unsafe { rflags::read() };
+ let flags = rflags::read();
if flags.contains(RFlags::FLAGS_ZF) {
Err(VmFail::VmFailValid)
@@ -26,12 +26,18 @@ fn vmx_capture_status() -> Result<()> {
///
/// `addr` specifies a 4KB-aligned physical address of VMXON region initialized
/// in accordance with Intel SDM, Volume 3C, Section 24.11.5.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmxon(addr: u64) -> Result<()> {
llvm_asm!("vmxon $0" : /* no outputs */ : "m"(addr));
vmx_capture_status()
}
/// Disable VMX operation.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmxoff() -> Result<()> {
llvm_asm!("vmxoff");
vmx_capture_status()
@@ -41,6 +47,9 @@ pub unsafe fn vmxoff() -> Result<()> {
///
/// Ensures that VMCS data maintained on the processor is copied to the VMCS region
/// located at 4KB-aligned physical address `addr` and initializes some parts of it.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmclear(addr: u64) -> Result<()> {
llvm_asm!("vmclear $0" : /* no outputs */ : "m"(addr));
vmx_capture_status()
@@ -49,12 +58,18 @@ pub unsafe fn vmclear(addr: u64) -> Result<()> {
/// Load current VMCS pointer.
///
/// Marks the current-VMCS pointer valid and loads it with the physical address `addr`.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
llvm_asm!("vmptrld $0" : /* no outputs */ : "m"(addr));
vmx_capture_status()
}
/// Return current VMCS pointer.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmptrst() -> Result<u64> {
let value: u64 = 0;
llvm_asm!("vmptrst ($0)" : /* no outputs */ : "r"(&value) : "memory");
@@ -62,6 +77,9 @@ pub unsafe fn vmptrst() -> Result<u64> {
}
/// Read a specified field from a VMCS.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmread(field: u32) -> Result<u64> {
let field: u64 = field.into();
let value: u64;
@@ -70,6 +88,9 @@ pub unsafe fn vmread(field: u32) -> Result<u64> {
}
/// Write to a specified field in a VMCS.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
let field: u64 = field.into();
llvm_asm!("vmwrite $1, $0" : /* no outputs */ : "r"(field), "r"(value));
@@ -77,6 +98,9 @@ pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
}
/// Launch virtual machine.
+///
+/// # Safety
+/// Needs CPL 0.
#[inline(always)]
pub unsafe fn vmlaunch() -> Result<()> {
llvm_asm!("vmlaunch");
@@ -84,6 +108,9 @@ pub unsafe fn vmlaunch() -> Result<()> {
}
/// Resume virtual machine.
+///
+/// # Safety
+/// Needs CPL 0.
#[inline(always)]
pub unsafe fn vmresume() -> Result<()> {
llvm_asm!("vmresume");
diff --git a/src/controlregs.rs b/src/controlregs.rs
index 00117ea..c9457f7 100644
--- a/src/controlregs.rs
+++ b/src/controlregs.rs
@@ -88,6 +88,9 @@ bitflags! {
}
/// Read cr0
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr0() -> Cr0 {
let ret: usize;
llvm_asm!("mov %cr0, $0" : "=r" (ret));
@@ -95,11 +98,17 @@ pub unsafe fn cr0() -> Cr0 {
}
/// Write cr0.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr0_write(val: Cr0) {
llvm_asm!("mov $0, %cr0" :: "r" (val.bits) : "memory");
}
/// Contains page-fault linear address.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr2() -> usize {
let ret: usize;
llvm_asm!("mov %cr2, $0" : "=r" (ret));
@@ -107,11 +116,17 @@ pub unsafe fn cr2() -> usize {
}
/// Write cr2, for instance to reset cr2
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr2_write(val: u64) {
llvm_asm!("mov $0, %cr2" :: "r" (val) : "memory");
}
/// Contains page-table root pointer.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr3() -> u64 {
let ret: u64;
llvm_asm!("mov %cr3, $0" : "=r" (ret));
@@ -119,11 +134,17 @@ pub unsafe fn cr3() -> u64 {
}
/// Switch page-table PML4 pointer.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr3_write(val: u64) {
llvm_asm!("mov $0, %cr3" :: "r" (val) : "memory");
}
/// Contains various flags to control operations in protected mode.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr4() -> Cr4 {
let ret: usize;
llvm_asm!("mov %cr4, $0" : "=r" (ret));
@@ -141,18 +162,27 @@ pub unsafe fn cr4() -> Cr4 {
/// cr4_write(cr4);
/// }
/// ```
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn cr4_write(val: Cr4) {
llvm_asm!("mov $0, %cr4" :: "r" (val.bits) : "memory");
}
/// Read Extended Control Register XCR0.
/// Only supported if CR4_ENABLE_OS_XSAVE is set.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn xcr0() -> Xcr0 {
Xcr0::from_bits_truncate(_xgetbv(0))
}
/// Write to Extended Control Register XCR0.
/// Only supported if CR4_ENABLE_OS_XSAVE is set.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn xcr0_write(val: Xcr0) {
_xsetbv(0, val.bits);
}
diff --git a/src/dtables.rs b/src/dtables.rs
index 780d6d4..d53113f 100644
--- a/src/dtables.rs
+++ b/src/dtables.rs
@@ -55,11 +55,17 @@ impl<T> fmt::Debug for DescriptorTablePointer<T> {
}
/// Load the GDTR register with the specified base and limit.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn lgdt<T>(gdt: &DescriptorTablePointer<T>) {
llvm_asm!("lgdt ($0)" :: "r" (gdt) : "memory");
}
/// Retrieve base and limit from the GDTR register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
llvm_asm!("sgdt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}
@@ -71,6 +77,9 @@ pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
/// the processor uses the segment selector to locate
/// the segment descriptor for the LDT in the global
/// descriptor table (GDT).
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_ldtr(selector: SegmentSelector) {
llvm_asm!("lldt $0" :: "r" (selector.bits()) : "memory");
}
@@ -79,6 +88,9 @@ pub unsafe fn load_ldtr(selector: SegmentSelector) {
///
/// The returned segment selector points to the segment descriptor
/// (located in the GDT) for the current LDT.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn ldtr() -> SegmentSelector {
let selector: u16;
llvm_asm!("sldt $0" : "=r"(selector));
@@ -86,11 +98,17 @@ pub unsafe fn ldtr() -> SegmentSelector {
}
/// Load the IDTR register with the specified base and limit.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn lidt<T>(idt: &DescriptorTablePointer<T>) {
llvm_asm!("lidt ($0)" :: "r" (idt) : "memory");
}
/// Retrieve base and limit from the IDTR register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn sidt<T>(idt: &mut DescriptorTablePointer<T>) {
llvm_asm!("sidt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}
diff --git a/src/io.rs b/src/io.rs
index 6b1139b..87c05f3 100644
--- a/src/io.rs
+++ b/src/io.rs
@@ -1,12 +1,18 @@
//! I/O port functionality.
/// Write 8 bits to port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn outb(port: u16, val: u8) {
llvm_asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(val));
}
/// Read 8 bits from port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn inb(port: u16) -> u8 {
let ret: u8;
@@ -15,12 +21,18 @@ pub unsafe fn inb(port: u16) -> u8 {
}
/// Write 16 bits to port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn outw(port: u16, val: u16) {
llvm_asm!("outw %ax, %dx" :: "{dx}"(port), "{al}"(val));
}
/// Read 16 bits from port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn inw(port: u16) -> u16 {
let ret: u16;
@@ -29,12 +41,18 @@ pub unsafe fn inw(port: u16) -> u16 {
}
/// Write 32 bits to port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn outl(port: u16, val: u32) {
llvm_asm!("outl %eax, %dx" :: "{dx}"(port), "{al}"(val));
}
/// Read 32 bits from port
+///
+/// # Safety
+/// Needs IO privileges.
#[inline]
pub unsafe fn inl(port: u16) -> u32 {
let ret: u32;
diff --git a/src/msr.rs b/src/msr.rs
index e6a377e..5f3a856 100644
--- a/src/msr.rs
+++ b/src/msr.rs
@@ -1,6 +1,9 @@
//! MSR value list and function to read and write them.
/// Write 64 bits to msr register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn wrmsr(msr: u32, value: u64) {
let low = value as u32;
let high = (value >> 32) as u32;
@@ -8,6 +11,9 @@ pub unsafe fn wrmsr(msr: u32, value: u64) {
}
/// Read 64 bits msr register.
+///
+/// # Safety
+/// Needs CPL 0.
#[allow(unused_mut)]
pub unsafe fn rdmsr(msr: u32) -> u64 {
let (high, low): (u32, u32);
diff --git a/src/random.rs b/src/random.rs
index 4388352..a53d724 100644
--- a/src/random.rs
+++ b/src/random.rs
@@ -6,8 +6,8 @@
//!
//! See also: https://software.intel.com/en-us/blogs/2012/11/17/the-difference-between-rdrand-and-rdseed
//!
-//! * RDRAND: Cryptographically secure pseudorandom number generator NIST:SP 800-90A
-//! * RDSEED: Non-deterministic random bit generator NIST: SP 800-90B & C (drafts)
+//! * RDRAND: Cryptographically secure pseudorandom number generator NIST:SP 800-90A
+//! * RDSEED: Non-deterministic random bit generator NIST: SP 800-90B & C (drafts)
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::{
_rdrand16_step, _rdrand32_step, _rdrand64_step, _rdseed16_step, _rdseed32_step, _rdseed64_step,
@@ -18,7 +18,7 @@ use core::arch::x86::{_rdrand16_step, _rdrand32_step, _rdseed16_step, _rdseed32_
/// Generates a 16-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDRAND instructions are not supported.
#[inline(always)]
pub unsafe fn rdrand16(e: &mut u16) -> bool {
@@ -27,7 +27,7 @@ pub unsafe fn rdrand16(e: &mut u16) -> bool {
/// Generates a 32-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDRAND instructions are not supported.
#[inline(always)]
pub unsafe fn rdrand32(e: &mut u32) -> bool {
@@ -36,7 +36,7 @@ pub unsafe fn rdrand32(e: &mut u32) -> bool {
/// Generates a 64-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDRAND instructions are not supported.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
@@ -48,7 +48,7 @@ pub unsafe fn rdrand64(e: &mut u64) -> bool {
pub trait RdRand {
/// Fills `self` with random bits. Returns true on success or false otherwise
///
- /// # Unsafe
+ /// # Safety
/// RDRAND is not supported on all architctures, so using this may crash you.
unsafe fn fill_random(&mut self) -> bool;
}
@@ -56,7 +56,7 @@ pub trait RdRand {
impl RdRand for u8 {
/// Fills the 16-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDSEED instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
let mut r: u16 = 0;
@@ -69,7 +69,7 @@ impl RdRand for u8 {
impl RdRand for u16 {
/// Fills the 16-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDRAND instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdrand16(self)
@@ -79,7 +79,7 @@ impl RdRand for u16 {
impl RdRand for u32 {
/// Fills the 32-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDRAND instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdrand32(self)
@@ -90,7 +90,7 @@ impl RdRand for u32 {
impl RdRand for u64 {
/// Fills the 64-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDRAND instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdrand64(self)
@@ -101,6 +101,8 @@ impl RdRand for u64 {
///
/// Returns true if the iterator was successfully filled with
/// random values, otherwise false.
+/// # Safety
+/// Will crash if RDRAND instructions are not supported.
pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool {
let mut worked = true;
for element in buffer {
@@ -111,7 +113,7 @@ pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool {
/// Generates a 16-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDSEED instructions are not supported.
#[inline(always)]
pub unsafe fn rdseed16(e: &mut u16) -> bool {
@@ -120,7 +122,7 @@ pub unsafe fn rdseed16(e: &mut u16) -> bool {
/// Generates a 32-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDSEED instructions are not supported.
#[inline(always)]
pub unsafe fn rdseed32(e: &mut u32) -> bool {
@@ -129,7 +131,7 @@ pub unsafe fn rdseed32(e: &mut u32) -> bool {
/// Generates a 64-bit random value and stores it in `e`.
///
-/// # Unsafe
+/// # Safety
/// Will crash if RDSEED instructions are not supported.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
@@ -141,7 +143,7 @@ pub unsafe fn rdseed64(e: &mut u64) -> bool {
pub trait RdSeed {
/// Fills `self` with random bits. Returns true on success or false otherwise
///
- /// # Unsafe
+ /// # Safety
/// RDSEED is not supported on all architctures, so using this may crash you.
unsafe fn fill_random(&mut self) -> bool;
}
@@ -149,7 +151,7 @@ pub trait RdSeed {
impl RdSeed for u8 {
/// Fills the 16-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDSEED instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
let mut r: u16 = 0;
@@ -162,7 +164,7 @@ impl RdSeed for u8 {
impl RdSeed for u16 {
/// Fills the 16-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDSEED instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdseed16(self)
@@ -172,7 +174,7 @@ impl RdSeed for u16 {
impl RdSeed for u32 {
/// Fills the 32-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDSEED instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdseed32(self)
@@ -183,7 +185,7 @@ impl RdSeed for u32 {
impl RdSeed for u64 {
/// Fills the 64-bit value with a random bit string
///
- /// # Unsafe
+ /// # Safety
/// Will crash if RDSEED instructions are not supported.
unsafe fn fill_random(&mut self) -> bool {
rdseed64(self)
@@ -194,6 +196,9 @@ impl RdSeed for u64 {
///
/// Returns true if the iterator was successfully filled with
/// random values, otherwise false.
+///
+/// # Safety
+/// Will crash if RDSEED instructions are not supported.
pub unsafe fn rdseed_slice<T: RdSeed>(buffer: &mut [T]) -> bool {
let mut worked = true;
for element in buffer {
diff --git a/src/segmentation.rs b/src/segmentation.rs
index 5ead88c..3ff748a 100644
--- a/src/segmentation.rs
+++ b/src/segmentation.rs
@@ -87,6 +87,7 @@ impl fmt::Display for SegmentSelector {
/// System-Segment and Gate-Descriptor Types 64-bit mode
/// See also Intel 3a, Table 3-2 System Segment and Gate-Descriptor Types.
+#[allow(clippy::upper_case_acronyms)]
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SystemDescriptorTypes64 {
@@ -110,6 +111,7 @@ pub enum SystemDescriptorTypes64 {
/// System-Segment and Gate-Descriptor Types 32-bit mode.
/// See also Intel 3a, Table 3-2 System Segment and Gate-Descriptor Types.
+#[allow(clippy::upper_case_acronyms)]
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SystemDescriptorTypes32 {
@@ -435,11 +437,15 @@ impl Descriptor {
}
pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) {
- if let Some(ring) = builder.dpl { self.set_dpl(ring) }
- if let Some((base, limit)) = builder
- .base_limit { self.set_base_limit(base as u32, limit as u32) }
- if let Some((selector, offset)) = builder
- .selector_offset { self.set_selector_offset(selector, offset as u32) }
+ if let Some(ring) = builder.dpl {
+ self.set_dpl(ring)
+ }
+ if let Some((base, limit)) = builder.base_limit {
+ self.set_base_limit(base as u32, limit as u32)
+ }
+ if let Some((selector, offset)) = builder.selector_offset {
+ self.set_selector_offset(selector, offset as u32)
+ }
if builder.present {
self.set_p();
@@ -551,26 +557,41 @@ impl Descriptor {
}
/// Reload stack segment register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_ss(sel: SegmentSelector) {
llvm_asm!("movw $0, %ss " :: "r" (sel.bits()) : "memory");
}
/// Reload data segment register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_ds(sel: SegmentSelector) {
llvm_asm!("movw $0, %ds " :: "r" (sel.bits()) : "memory");
}
/// Reload es segment register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_es(sel: SegmentSelector) {
llvm_asm!("movw $0, %es " :: "r" (sel.bits()) : "memory");
}
/// Reload fs segment register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_fs(sel: SegmentSelector) {
llvm_asm!("movw $0, %fs " :: "r" (sel.bits()) : "memory");
}
/// Reload gs segment register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_gs(sel: SegmentSelector) {
llvm_asm!("movw $0, %gs " :: "r" (sel.bits()) : "memory");
}
diff --git a/src/task.rs b/src/task.rs
index 40fdc2c..a7b3423 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -11,6 +11,9 @@ pub fn tr() -> segmentation::SegmentSelector {
}
/// Loads the task register.
+///
+/// # Safety
+/// Needs CPL 0.
pub unsafe fn load_tr(sel: segmentation::SegmentSelector) {
llvm_asm!("ltr $0" :: "r" (sel.bits()));
}