Skip to content
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
694 changes: 422 additions & 272 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ V9P ?= n
BUS ?= mmio
RISCV_BIOS ?= default
GICV3 ?= n
RNG ?= n

DISK_IMG ?= disk.img
FS ?= fat32
Expand Down
3 changes: 3 additions & 0 deletions api/ruxfeat/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ display = [
"ruxruntime/display",
]

#virtio random number generator
virtio-rng = ["ruxdriver/virtio-rng","ruxruntime/rng","ruxfs/rng"]

# 9P
virtio-9p = [
"9pfs",
Expand Down
5 changes: 5 additions & 0 deletions api/ruxos_posix_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ poll = ["fd"]
tls = ["ruxfeat/tls"]
irq = ["ruxfeat/irq"]
random-hw = []
rng = ["ruxrand"]
virtio-rng = ["driver_virtio/rng","rng"]

musl = ["ruxhal/musl", "ruxruntime/musl", "axalloc/slab", "ruxtask/musl"]

Expand All @@ -52,6 +54,7 @@ ruxtask = { path = "../../modules/ruxtask", features = [
ruxfs = { path = "../../modules/ruxfs", optional = true }
ruxfuse = { path = "../../modules/ruxfuse", optional = true }
ruxnet = { path = "../../modules/ruxnet", optional = true }
ruxrand = { path = "../../modules/ruxrand", optional = true }

# Other crates
tty = { path = "../../crates/tty" }
Expand All @@ -69,6 +72,8 @@ flatten_objects = { path = "../../crates/flatten_objects" }
page_table = { path = "../../crates/page_table" }
crate_interface = "0.1.1"
capability = { path = "../../crates/capability" }
driver_virtio = { path = "../../crates/driver_virtio" }


cfg-if = "1.0"
elf = { version = "0.7", default-features = false }
Expand Down
69 changes: 44 additions & 25 deletions api/ruxos_posix_api/src/imp/getrandom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::ctypes::{size_t, ssize_t};

use axerrno::LinuxError;

#[cfg(all(target_arch = "x86_64", feature = "random-hw"))]
#[cfg(all(target_arch = "x86_64", feature = "random-hw", not(feature = "rng")))]
use core::arch::x86_64::__cpuid;

static SEED: AtomicU64 = AtomicU64::new(0xae_f3);
Expand Down Expand Up @@ -53,7 +53,7 @@ fn srand_lcg(seed: u64) {
}

/// Checking if the CPU core is compatible with hardware random number instructions.
#[cfg(feature = "random-hw")]
#[cfg(all(feature = "random-hw", not(feature = "rng")))]
fn has_rdrand() -> bool {
#[cfg(target_arch = "x86_64")]
{
Expand All @@ -77,7 +77,7 @@ fn has_rdrand() -> bool {
}

/// Return 64-bit unsigned random interger using cpu instruction
#[cfg(feature = "random-hw")]
#[cfg(all(feature = "random-hw", not(feature = "rng")))]
fn random_hw() -> u64 {
let mut _random: u64;

Expand Down Expand Up @@ -118,33 +118,38 @@ pub unsafe extern "C" fn sys_srand(_seed: c_uint) {
/// Returns a 32-bit unsigned random integer
#[no_mangle]
pub unsafe extern "C" fn sys_rand() -> c_int {
#[cfg(feature = "random-hw")]
#[cfg(all(feature = "rng", not(feature = "random-hw")))]
{
match has_rdrand() {
true => (random_hw() >> 33) as c_int,
false => rand_lcg32() as c_int,
}
use ruxrand::random;
return random::<c_int>();
}
#[cfg(not(feature = "random-hw"))]
#[cfg(all(feature = "random-hw", not(feature = "rng")))]
{
rand_lcg32() as c_int
match has_rdrand() {
true => return (random_hw() >> 33) as c_int,
false => return rand_lcg32() as c_int,
}
}
rand_lcg32() as c_int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: unreachable expression
   --> api/ruxos_posix_api/src/imp/getrandom.rs:133:5
    |
128 | /         match has_rdrand() {
129 | |             true => return (random_hw() >> 33) as c_int,
130 | |             false => return rand_lcg32() as c_int,
131 | |         }
    | |_________- any code following this `match` expression is unreachable, as all arms diverge
132 |       }
133 |       rand_lcg32() as c_int
    |       ^^^^^^^^^^^^^^^^^^^^^ unreachable expression
    |
    = note: `#[warn(unreachable_code)]` on by default

warning: unreachable expression
   --> api/ruxos_posix_api/src/imp/getrandom.rs:152:5
    |
146 | /         match has_rdrand() {
147 | |             true => return (random_hw() >> 1) as c_long,
148 | |             false => return random_lcg64() as c_long,
149 | |         }
    | |_________- any code following this `match` expression is unreachable, as all arms diverge
...
152 |       random_lcg64() as c_long
    |       ^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression

}

/// Returns a 64-bit unsigned random integer
#[no_mangle]
pub unsafe extern "C" fn sys_random() -> c_long {
#[cfg(feature = "random-hw")]
#[cfg(all(feature = "rng", not(feature = "random-hw")))]
{
match has_rdrand() {
true => (random_hw() >> 1) as c_long,
false => random_lcg64() as c_long,
}
use ruxrand::random;
return random::<c_long>();
}
#[cfg(not(feature = "random-hw"))]
#[cfg(all(feature = "random-hw", not(feature = "rng")))]
{
random_lcg64() as c_long
match has_rdrand() {
true => return (random_hw() >> 1) as c_long,
false => return random_lcg64() as c_long,
}
}

random_lcg64() as c_long
}

/// Fills the buffer pointed to by buf with up to buflen random bytes.
Expand All @@ -159,15 +164,29 @@ pub unsafe extern "C" fn sys_getrandom(buf: *mut c_void, buflen: size_t, flags:
if flags != 0 {
warn!("flags are not implemented yet, flags: {flags}, ignored");
}
// fill the buffer 8 bytes at a time first, then fill the remaining bytes
let buflen_mod = buflen % (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
let buflen_div = buflen / (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
for i in 0..buflen_div {
*((buf as *mut u8 as *mut i64).add(i)) = sys_random() as i64;
#[cfg(feature = "rng")]
{
use ruxrand::request_entropy;
let slice: &mut [u8] =
unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, buflen) };
request_entropy(slice).map_err(|e| {
warn!("Failed to get random bytes: {e:?}");
LinuxError::EIO
})?;
Ok(buflen as ssize_t)
}
for i in 0..buflen_mod {
*((buf as *mut u8).add(buflen - buflen_mod + i)) = sys_rand() as u8;
#[cfg(not(feature = "rng"))]
{
// fill the buffer 8 bytes at a time first, then fill the remaining bytes
let buflen_mod = buflen % (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
let buflen_div = buflen / (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
for i in 0..buflen_div {
*((buf as *mut u8 as *mut i64).add(i)) = sys_random() as i64;
}
for i in 0..buflen_mod {
*((buf as *mut u8).add(buflen - buflen_mod + i)) = sys_rand() as u8;
}
Ok(buflen as ssize_t)
}
Ok(buflen as ssize_t)
})
}
2 changes: 1 addition & 1 deletion apps/c/libc-bench/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- Run with following command
```
make A=apps/c/libc-bench/ MUSL=y BLK=y ARCH=aarch64 LOG=error SMP=4 run
make A=apps/c/libc-bench/ MUSL=y BLK=y RNG=y ARCH=aarch64 LOG=error SMP=4 run
```

- This benchmark includes (all codes are really simple to read):
Expand Down
1 change: 1 addition & 0 deletions apps/c/random/features.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
virtio-rng
30 changes: 30 additions & 0 deletions apps/c/random/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] 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.
*/

#define _GNU_SOURCE
#include <sys/random.h>
#include <stdio.h>

int main() {
printf("Using getrandom to fetch random bytes...\n");
unsigned char buf[16];
ssize_t n = getrandom(buf, sizeof(buf), 0);
if (n < 0) {
perror("getrandom");
return 1;
}

printf("Random bytes:\n");
for (int i = 0; i < n; ++i) {
printf("%02x ", buf[i]);
}
printf("\n");

return 0;
}
2 changes: 2 additions & 0 deletions crates/driver_common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub enum DeviceType {
Display,
/// Plan-9 device (e.g. 9pfs)
_9P,
/// Random number generator device.
Rng,
}

/// The error type for device operation failures.
Expand Down
28 changes: 28 additions & 0 deletions crates/driver_rng/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "driver_rng"
version = "0.1.0"
edition = "2021"
authors = ["Haowen Liu <[email protected]>"]
description = "Common traits and types for random number generator device drivers"
license = "Mulan PSL v2"
homepage = "https://github.com/syswonder/ruxos"
repository = "https://github.com/syswonder/ruxos/tree/main/crates/driver_rng"

[features]
default = []
xoshiro= ["dep:rand_xoshiro"]

easy-spin = []

[dependencies]
driver_common = { path = "../driver_common" }
crate_interface = "0.1.1"
rand = { version = "0.8.5", default-features = false }
rand_xoshiro = { version = "0.6.0", default-features = false, optional = true }

spinlock = { version = "0.1.0", path = "../../crates/spinlock" }
percpu = "0.2"
lazy_init = { version = "0.1.0", path = "../../crates/lazy_init", default-features = false }

[dev-dependencies]
rand = { version = "0.8.5" }
27 changes: 27 additions & 0 deletions crates/driver_rng/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] 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.
*/

//! Common traits and types for random number generator device drivers.

#![no_std]

#[doc(no_inline)]
pub use driver_common::{BaseDriverOps, DevError, DevResult, DeviceType};

/// The information of the graphics device.
#[derive(Debug, Clone, Copy)]
pub struct RngInfo {}

/// Operations that require a graphics device driver to implement.
pub trait RngDriverOps: BaseDriverOps {
/// Get the random number generator information.
fn info(&self) -> RngInfo;
/// Request random bytes from the device.
fn request_entropy(&mut self, dst: &mut [u8]) -> DevResult<usize>;
}
2 changes: 2 additions & 0 deletions crates/driver_virtio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ net = ["driver_net"]
gpu = ["driver_display"]
v9p = ["driver_9p"]
console = ["driver_console"]
rng = ["driver_rng"]

[dependencies]
log = { workspace = true }
Expand All @@ -28,4 +29,5 @@ driver_net = { path = "../driver_net", optional = true }
driver_display = { path = "../driver_display", optional = true }
driver_9p = { path = "../driver_9p", optional = true }
driver_console = { path = "../driver_console", optional = true }
driver_rng = { path = "../driver_rng", optional = true }
virtio-drivers = { git = "https://github.com/syswonder/virtio-drivers.git", rev = "31f6555" }
5 changes: 5 additions & 0 deletions crates/driver_virtio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ mod console;
mod gpu;
#[cfg(feature = "net")]
mod net;
#[cfg(feature = "rng")]
mod rng;
#[cfg(feature = "v9p")]
mod v9p;

Expand All @@ -42,6 +44,8 @@ pub use self::console::VirtIoConsoleDev;
pub use self::gpu::VirtIoGpuDev;
#[cfg(feature = "net")]
pub use self::net::VirtIoNetDev;
#[cfg(feature = "rng")]
pub use self::rng::VirtIoRngDev;
#[cfg(feature = "v9p")]
pub use self::v9p::VirtIo9pDev;

Expand Down Expand Up @@ -99,6 +103,7 @@ const fn as_dev_type(t: VirtIoDevType) -> Option<DeviceType> {
GPU => Some(DeviceType::Display),
_9P => Some(DeviceType::_9P),
Console => Some(DeviceType::Char),
EntropySource => Some(DeviceType::Rng),
_ => None,
}
}
Expand Down
60 changes: 60 additions & 0 deletions crates/driver_virtio/src/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] 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.
*/

extern crate alloc;
use crate::as_dev_err;

use driver_common::{BaseDriverOps, DevResult, DeviceType};
use driver_rng::{RngDriverOps, RngInfo};
use virtio_drivers::{device::rng::VirtIORng as InnerDev, transport::Transport, Hal};

/// The VirtIO RNG device driver.
pub struct VirtIoRngDev<H: Hal, T: Transport> {
inner: InnerDev<H, T>,
info: RngInfo,
}

unsafe impl<H: Hal, T: Transport> Send for VirtIoRngDev<H, T> {}
unsafe impl<H: Hal, T: Transport> Sync for VirtIoRngDev<H, T> {}

impl<H: Hal, T: Transport> VirtIoRngDev<H, T> {
/// Creates a new driver instance and initializes the device, or returns
/// an error if any step fails.
pub fn try_new(transport: T) -> DevResult<Self> {
let virtio = InnerDev::new(transport).unwrap();
let info = RngInfo {};
Ok(Self {
inner: virtio,
info,
})
}
}

impl<H: Hal, T: Transport> RngDriverOps for VirtIoRngDev<H, T> {
fn info(&self) -> RngInfo {
self.info
}

fn request_entropy(&mut self, dst: &mut [u8]) -> DevResult<usize> {
match self.inner.request_entropy(dst) {
Ok(size) => Ok(size),
Err(e) => Err(as_dev_err(e)),
}
}
}

impl<H: Hal, T: Transport> const BaseDriverOps for VirtIoRngDev<H, T> {
fn device_name(&self) -> &str {
"virtio-rng"
}

fn device_type(&self) -> DeviceType {
DeviceType::Rng
}
}
Loading
Loading