Skip to content

Commit

Permalink
add feature to generate random based on cpu instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
ken4647 committed Sep 13, 2023
1 parent 2f51976 commit 1ae6fdd
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 17 deletions.
9 changes: 9 additions & 0 deletions api/arceos_posix_api/src/imp/io_mpx/poll.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Rukos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

use crate::{
ctypes,
imp::fd_ops::get_file_like,
Expand Down
2 changes: 1 addition & 1 deletion scripts/make/features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
ifeq ($(APP_TYPE),c)
ax_feat_prefix := axfeat/
lib_feat_prefix := axlibc/
lib_features := fp_simd alloc multitask fs net fd pipe select poll epoll
lib_features := fp_simd alloc multitask fs net fd pipe select poll epoll random-hw
else
# TODO: it's better to use `axfeat/` as `ax_feat_prefix`, but all apps need to have `axfeat` as a dependency
ax_feat_prefix := axstd/
Expand Down
1 change: 1 addition & 0 deletions ulib/axlibc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pipe = ["arceos_posix_api/pipe"]
select = ["arceos_posix_api/select"]
poll = ["arceos_posix_api/poll"]
epoll = ["arceos_posix_api/epoll"]
random-hw = []

[dependencies]
axfeat = { path = "../../api/axfeat" }
Expand Down
131 changes: 115 additions & 16 deletions ulib/axlibc/src/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,133 @@
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

//! Random number generator.

use core::{
ffi::{c_int, c_long, c_uint},
sync::atomic::{AtomicU64, Ordering::SeqCst},
ffi::{c_int,c_long,c_uint},
sync::atomic::{AtomicU64,Ordering::SeqCst},
};

#[cfg(not(feature = "random-hw"))]
static SEED: AtomicU64 = AtomicU64::new(0xa2ce_a2ce);

/// Sets the seed for the random number generator.
/// Returns a 32-bit unsigned pseudo random interger from LCG.
#[cfg(not(feature = "random-hw"))]
fn random_lcg_32() -> u32 {
let new_seed = SEED.load(SeqCst).wrapping_mul(25214903917).wrapping_add(11);
SEED.store(new_seed, SeqCst);
new_seed as u32
}

/// Returns a 64-bit unsigned pseudo random interger from LCG.
#[cfg(not(feature = "random-hw"))]
fn random_lcg_64() -> u64 {
let new_seed = SEED.load(SeqCst).wrapping_mul(6364136223846793005) + 1442695040888963407;
SEED.store(new_seed, SeqCst);
new_seed as u64
}

/// Sets the seed for the random number generator implemented by LCG.
#[cfg(not(feature = "random-hw"))]
fn srand_lcg(seed: u64) {
SEED.store(seed, SeqCst);
}

/// Checking if the CPU core is compatible with hardware random number instructions.
#[cfg(feature = "random-hw")]
fn has_rdrand() -> bool{
#[cfg(target_arch = "x86_64")]{
let mut ecx:u32;
unsafe{
core::arch::asm!(
"mov eax, 1",
"cpuid",
out("ecx") ecx
)
}
ecx&(1<<30)!=0
}
#[cfg(target_arch = "aarch64")]{
let mut ID_AA64ISAR0_EL1:u64;
unsafe{
core::arch::asm!(
"mrs {},ID_AA64ISAR0_EL1",
out(reg) ID_AA64ISAR0_EL1
)
}
ID_AA64ISAR0_EL1&(0b1111<<60) == 0b0001<<60
}
#[cfg(target_arch = "riscv64")]{
false
}
}

/// Return 64-bit unsigned random interger from cpu instruction
#[cfg(feature = "random-hw")]
fn random_hw() -> u64 {
let mut rand:u64;

#[cfg(target_arch = "x86_64")]
unsafe{
core::arch::asm!{
"rdrand {0:r}",
out(reg) rand
}
}

#[cfg(target_arch = "aarch64")]
unsafe{
core::arch::asm!{
"mrs {}, s3_3_c2_c4_0", // s3_3_c2_c4_0 is register `rndr`
out(reg) rand
}
}

#[cfg(target_arch = "riscv64")]{
panic!("riscv64 has no rdrand instructions")
}

rand as u64
}

/// Sets the seed for the random number generator implemented by LCG.
#[no_mangle]
pub unsafe extern "C" fn srand(seed: c_uint) {
SEED.store(seed.wrapping_sub(1) as u64, SeqCst);
pub unsafe extern "C" fn srand(_seed: c_uint) {
#[cfg(not(feature = "random-hw"))]{
srand_lcg(_seed as u64);
}
}

/// Returns a 32-bit unsigned pseudo random interger.
/// Returns a 32-bit unsigned random integer
#[no_mangle]
pub unsafe extern "C" fn rand() -> c_int {
let new_seed = SEED.load(SeqCst).wrapping_mul(6364136223846793005) + 1;
SEED.store(new_seed, SeqCst);
(new_seed >> 33) as c_int
#[cfg(feature = "random-hw")]{
match has_rdrand() {
true => {
random_hw() as c_int
}
false => {
random_lcg_32() as c_int
}
}
}
#[cfg(not(feature = "random-hw"))]{
random_lcg_32() as c_int
}
}

/// Returns a 64-bit unsigned pseudo random number.
/// Returns a 64-bit unsigned random integer
#[no_mangle]
pub unsafe extern "C" fn random() -> c_long {
let new_seed = SEED.load(SeqCst).wrapping_mul(6364136223846793005) + 1;
SEED.store(new_seed, SeqCst);
new_seed as c_long
#[cfg(feature = "random-hw")]{
match has_rdrand() {
true => {
random_hw() as c_long
}
false => {
random_lcg_64() as c_long
}
}
}
#[cfg(not(feature = "random-hw"))]{
random_lcg_64() as c_long
}
}

0 comments on commit 1ae6fdd

Please sign in to comment.