Skip to content
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

WIP: Simple Rust driver that touches real hardware #254

Closed
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ jobs:
- run: make ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_SYSROOT }} -j3 CLIPPY=1

# Docs
- run: make ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_SYSROOT }} -j3 rustdoc
#- run: make ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_SYSROOT }} -j3 rustdoc

# Formatting
- run: make rustfmtcheck
189 changes: 189 additions & 0 deletions arch/arm/configs/bcm2835_rust_defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_NAMESPACES=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_RUST=y
CONFIG_ARCH_MULTI_V6=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM2835=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
CONFIG_VFP=y
# CONFIG_SUSPEND is not set
CONFIG_PM=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_CLEANCACHE=y
CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NETFILTER=y
CONFIG_BT=y
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_BCM=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
CONFIG_BCMGENET=y
CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_SMSC95XX=y
CONFIG_BRCMFMAC=m
CONFIG_ZD1211RW=y
CONFIG_INPUT_EVDEV=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_TTY_PRINTK=y
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_BCM2835 is not set
CONFIG_HW_RANDOM_BCM2835_RUST=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_BCM2835=y
CONFIG_SPI=y
CONFIG_SPI_BCM2835=y
CONFIG_SPI_BCM2835AUX=y
CONFIG_GPIO_SYSFS=y
CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_THERMAL=y
CONFIG_BCM2711_THERMAL=y
CONFIG_BCM2835_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_BCM2835_WDT=y
CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_DRM=y
CONFIG_DRM_VC4=y
CONFIG_FB_SIMPLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_BCM2835_SOC_I2S=y
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC2=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_USB_ETH_EEM=y
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_IPROC=y
CONFIG_MMC_BCM2835=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_STAGING=y
CONFIG_SND_BCM2835=m
CONFIG_VIDEO_BCM2835=m
CONFIG_CLK_RASPBERRYPI=y
CONFIG_MAILBOX=y
CONFIG_BCM2835_MBOX=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_RASPBERRYPI_POWER=y
CONFIG_PWM=y
CONFIG_PWM_BCM2835=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
# CONFIG_XZ_DEC_ARM is not set
# CONFIG_XZ_DEC_ARMTHUMB is not set
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_BOOT_PRINTK_DELAY=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_KGDB=y
CONFIG_KGDB_KDB=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_FUNCTION_PROFILER=y
CONFIG_STACK_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_SAMPLES=y
CONFIG_SAMPLES_RUST=y
CONFIG_STRICT_DEVMEM=y
CONFIG_TEST_KSTRTOX=y
14 changes: 14 additions & 0 deletions drivers/char/hw_random/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ config HW_RANDOM_BCM2835

If unsure, say Y.

config HW_RANDOM_BCM2835_RUST
tristate "Rust implementation of Broadcom BCM2835 Random Number Generator"
depends on HAS_RUST && ARCH_BCM2835
select REGMAP_MMIO
help
This driver provides alternative Rust-based kernel-side support
for the Random Number Generator hardware found on the Broadcom
BCM2835 SoC.

To compile this driver as a module, choose M here: the
module will be called bcm2835_rng_rust

If unsure, say N.

config HW_RANDOM_IPROC_RNG200
tristate "Broadcom iProc/STB RNG200 support"
depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB
Expand Down
1 change: 1 addition & 0 deletions drivers/char/hw_random/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835_RUST) += bcm2835_rng_rust.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
Expand Down
120 changes: 120 additions & 0 deletions drivers/char/hw_random/bcm2835_rng_rust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: GPL-2.0

//! Broadcom BCM2835 Random Number Generator support.

#![no_std]
#![feature(allocator_api, global_asm)]

use alloc::{boxed::Box, sync::Arc};
use core::pin::Pin;
use kernel::prelude::*;
use kernel::{
cstr,
file::File,
file_operations::{FileOpener, FileOperations},
io_buffer::IoBufferWriter,
miscdev,
platform_driver::{self, PlatformDevice, PlatformDriver},
regmap::{Regmap, RegmapConfig},
};

module! {
type: RngModule,
name: b"bcm2835_rng_rust",
author: b"Rust for Linux Contributors",
description: b"BCM2835 Random Number Generator (RNG) driver",
license: b"GPL v2",
}

struct SharedState {
regmap: Regmap,
}

impl SharedState {
fn try_new(regmap: Regmap) -> Result<Arc<Self>> {
Ok(Arc::try_new(SharedState { regmap })?)
}
}

struct RngDevice {
state: Arc<SharedState>,
}

impl FileOpener<Arc<SharedState>> for RngDevice {
fn open(state: &Arc<SharedState>) -> Result<Self::Wrapper> {
Ok(Box::try_new(RngDevice {
state: state.clone(),
})?)
}
}

impl FileOperations for RngDevice {
kernel::declare_file_operations!(read);

fn read<T: IoBufferWriter>(&self, _: &File, data: &mut T, offset: u64) -> Result<usize> {
// Succeed if the caller doesn't provide a buffer or if not at the start.
if data.is_empty() || offset != 0 {
return Ok(0);
}

let regmap = &self.state.regmap;
let num_words = regmap.read(RNG_STATUS)? >> 24;
if num_words == 0 {
return Ok(0);
}
data.write(&regmap.read(RNG_DATA)?)?;
Ok(4)
}
}

#[derive(Default)]
struct RngDriver;

// TODO: Issue #260 ("Use Rust type system to make Regmap API safer").

const RNG_CTRL: u32 = 0x0;
const RNG_STATUS: u32 = 0x4;
const RNG_DATA: u32 = 0x8;

// The initial numbers generated are "less random" so will be discarded.
const RNG_WARMUP_COUNT: u32 = 0x40000;
// Enable rng.
const RNG_RBGEN: u32 = 0x1;

impl PlatformDriver for RngDriver {
type DrvData = Pin<Box<miscdev::Registration<Arc<SharedState>>>>;

fn probe(pdev: &mut PlatformDevice) -> Result<Self::DrvData> {
// Create Regmap which maps device registers.
let cfg = RegmapConfig::new(32, 32)
.reg_stride(4)
.max_register(RNG_DATA);
let regmap = Regmap::init_mmio_platform_resource(pdev, 0, &cfg)?;
// Set warm-up count & enable.
regmap.write(RNG_STATUS, RNG_WARMUP_COUNT)?;
regmap.write(RNG_CTRL, RNG_RBGEN)?;
// Register character device so userspace can read out random data.
// TODO: use a `struct hwrng` instead of a `miscdev`.
let state = SharedState::try_new(regmap)?;
let dev = miscdev::Registration::new_pinned::<RngDevice>(cstr!("rust_hwrng"), None, state)?;
Ok(dev)
}
}

struct RngModule {
_pdev: Pin<Box<platform_driver::Registration>>,
}

impl KernelModule for RngModule {
fn init() -> Result<Self> {
let pdev = platform_driver::Registration::new_pinned::<RngDriver>(
cstr!("bcm2835-rng-rust"),
// TODO: this should be an optional list.
// Perhaps use an enum to specify behavioural differences.
cstr!("brcm,bcm2835-rng"),
&THIS_MODULE,
)?;

Ok(RngModule { _pdev: pdev })
}
}
Loading