Skip to content

arch/arm64/imx9: add an ELE-backed /dev/random driver - #20191

Draft
royzah wants to merge 3 commits into
apache:masterfrom
royzah:imx9-rng
Draft

royzah wants to merge 3 commits into
apache:masterfrom
royzah:imx9-rng

Conversation

@royzah

@royzah royzah commented Sep 19, 2026

Copy link
Copy Markdown

Summary

imx9_ele_get_random() exists, but nothing registers a device for it, so the i.MX9 entropy pool is never seeded from hardware. stm32h7, nrf52, lpc54xx and rp23xx all ship this driver; imx9 does not.

Modelled on https://github.com/apache/nuttx/blob/master/arch/arm/src/stm32h7/stm32_rng.c

Two points for review:

  • imx9_ele.c built only for CONFIG_IMX9_BOOTLOADER, putting the enclave out of reach of the application core. It moves behind a new CONFIG_IMX9_ELE that the bootloader selects, so existing configs are unchanged.
  • A transfer that never lands is silent, so the buffer is prefilled with a pattern and a block still holding it is refused, as is an all-zero block and, by the FIPS 140-2 continuous test, a repeat of the one before. Zero alone could not tell "the write never arrived" from "the ELE answered with zeros".

Impact

CONFIG_IMX9_RNG, off by default, registers /dev/random and /dev/urandom. i.MX9 only, no existing defconfig changes behaviour.

Depends on

The address-space fix in #20196, so the buffer reaches the enclave correctly under an MMU.

Testing

Compiles for imx93-evk:nsh with CONFIG_IMX9_RNG=y, tools/nxstyle clean.

That build is what caught the first version gating IMX9_ELE on IMX9_HAVE_MU, which only ARCH_CHIP_IMX95 selects, so the driver was unselectable on the chip it is for.

@github-actions github-actions Bot added Arch: arm64 Issues related to ARM64 (64-bit) architecture Area: OS Components OS Components issues Size: M The size of the change in this PR is medium labels Sep 19, 2026
bool "Bootloader"
select ARM64_DECODEFIQ if ARCH_ARM64_EXCEPTION_LEVEL = 3
select IMX9_DDR_TRAINING if ARCH_ARM64_EXCEPTION_LEVEL = 3
select IMX9_ELE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why select IMX9_ELE

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

imx9_trdc.c calls imx9_ele_init() and builds under IMX9_BOOTLOADER, so it won't link without this:
https://github.com/apache/nuttx/blob/master/arch/arm64/src/imx9/imx9_trdc.c#L760

Same pattern as IMX9_AHAB_BOOT a few lines down:
https://github.com/apache/nuttx/blob/master/arch/arm64/src/imx9/Kconfig#L116

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if so, let's remove the prompt string from option

Comment thread arch/arm64/src/imx9/Make.defs
@github-actions

github-actions Bot commented Sep 19, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@github-actions github-actions Bot removed the Area: OS Components OS Components issues label Sep 19, 2026
@royzah
royzah force-pushed the imx9-rng branch 3 times, most recently from e9abe14 to 6f61329 Compare September 19, 2026 16:39
up_addrenv_va_to_pa() is declared in include/nuttx/arch.h but implemented
only by armv7-a, so no arm64 port can map a virtual address to a physical
one. A driver whose device addresses memory physically has nothing to call.

The translation is asked of the MMU with AT S1E1R rather than walked in
software, so it answers for whatever is actually mapped: any granule size,
block or page, at any level, and it cannot drift from the tables in use.

PAR_EL1 is one register per CPU, so nothing may run between the translation
and reading the result. Interrupts are banked with it, so masking them
locally is sufficient and SMP needs nothing further.

Returns zero for an address that is not mapped for a privileged read, which
is what the declaration in arch.h specifies. Note this differs from the
armv7-a implementation, which returns the virtual address unchanged.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
…ual one.

The ELE addresses memory physically; cache maintenance takes a virtual
address. Both buffer calls supply one and use it for both, in opposite
directions: get_random() runs up_flush_dcache() on a physical address,
get_key() hands the enclave a virtual one. Both fail silently, and both
are correct only while the two are equal.

Take the virtual address in both, maintain the cache on it, and translate
for the message. get_random() also gains the alignment check get_key()
already has.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
The i.MX9 has a true random number generator behind the EdgeLock Enclave
and imx9_ele_get_random() to reach it, but nothing registers a character
device for it, so the entropy pool is never seeded from hardware. stm32h7,
nrf52, lpc54xx and rp23xx all provide one; imx9 does not.

imx9_ele.c was built only for CONFIG_IMX9_BOOTLOADER, putting the enclave
out of reach of the application core. It moves behind a new CONFIG_IMX9_ELE
that the bootloader selects, so existing configurations build as before.

A transfer that never lands is silent, so the buffer is prefilled with a
pattern and a block still holding it is refused, as is an all-zero block
and, by the FIPS 140-2 continuous test, a repeat of the one before.

Compiles for imx93-evk:nsh with CONFIG_IMX9_RNG=y.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm64 Issues related to ARM64 (64-bit) architecture Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants