Skip to content

Instantly share code, notes, and snippets.

@Amanieu
Created January 10, 2016 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Amanieu/0b9cf14d1fdc8927e948 to your computer and use it in GitHub Desktop.
Save Amanieu/0b9cf14d1fdc8927e948 to your computer and use it in GitHub Desktop.
// Generate a trap list entry as a usize, as appropriate for the current target.
#[cfg(target_pointer_width = "64")]
macro_rules! asm_trap_list {
() => {
".section safemem_trap_list, \"aw\";\
.quad 0b;\
.previous;"
};
}
#[cfg(target_pointer_width = "32")]
macro_rules! asm_trap_list {
() => {
".section safemem_trap_list, \"aw\";\
.word 0b;\
.previous;"
};
}
// Internal macros which record the location of a potentially faulting
// instruction.
macro_rules! asm_read {
($instr:expr, $width:expr, $success:expr, $esr:expr, $result:expr, $ptr:expr) => {
asm!(
concat!(
"0: ", $instr, " ${2:", $width, "}, $3;",
asm_trap_list!()
)
: "+{x17}" ($success), "={x16}" ($esr), "=r" ($result)
: "*m" ($ptr)
:
: "volatile"
)
};
}
macro_rules! asm_write {
($instr:expr, $width:expr, $success:expr, $esr:expr, $value:expr, $ptr:expr) => {
asm!(
concat!(
"0: ", $instr, " ${3:", $width, "}, $2;",
asm_trap_list!()
)
: "+{x17}" ($success), "={x16}" ($esr), "=*m" ($ptr)
: "r" ($value)
:
: "volatile"
)
};
}
pub unsafe fn safe_read<T: Copy>(ptr: *const T) -> Result<T, SafeMemError> {
let mut success: u64 = 1;
let mut result: T = mem::uninitialized();
let esr: u32;
match mem::size_of::<T>() {
1 => asm_read!("ldrb", "w", success, esr, result, ptr),
2 => asm_read!("ldrh", "w", success, esr, result, ptr),
4 => asm_read!("ldr", "w", success, esr, result, ptr),
8 => asm_read!("ldr", "x", success, esr, result, ptr),
_ => return safe_copy_nonoverlapping(ptr, &mut result, 1).map(|_| result),
}
if success != 0 {
Ok(result)
} else {
Err(SafeMemError { esr: esr })
}
}
pub unsafe fn safe_write<T: Copy>(ptr: *mut T, value: T) -> Result<(), SafeMemError> {
let mut success: u64 = 1;
let esr: u32;
match mem::size_of::<T>() {
1 => asm_write!("ldrb", "w", success, esr, value, ptr),
2 => asm_write!("ldrh", "w", success, esr, value, ptr),
4 => asm_write!("ldr", "w", success, esr, value, ptr),
8 => asm_write!("ldr", "x", success, esr, value, ptr),
_ => return safe_copy_nonoverlapping(&value, ptr, 1),
}
if success != 0 {
Ok(())
} else {
Err(SafeMemError { esr: esr })
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment