Skip to content
Draft
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
6 changes: 6 additions & 0 deletions arch/arm64/src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ endif()

if(CONFIG_ARCH_HAVE_MMU)
list(APPEND SRCS arm64_mmu.c)

# drivers/misc/addrenv.c defines the same entry points from a table.

if(NOT CONFIG_DEV_SIMPLE_ADDRENV)
list(APPEND SRCS arm64_physpgaddr.c)
endif()
endif()

if(CONFIG_ARM64_MTE)
Expand Down
6 changes: 6 additions & 0 deletions arch/arm64/src/common/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ endif

ifeq ($(CONFIG_ARCH_HAVE_MMU),y)
CMN_CSRCS += arm64_mmu.c

# drivers/misc/addrenv.c defines the same entry points from a table.

ifneq ($(CONFIG_DEV_SIMPLE_ADDRENV),y)
CMN_CSRCS += arm64_physpgaddr.c
endif
endif

ifeq ($(CONFIG_ARM64_MTE),y)
Expand Down
101 changes: 101 additions & 0 deletions arch/arm64/src/common/arm64_physpgaddr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/****************************************************************************
* arch/arm64/src/common/arm64_physpgaddr.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <stdint.h>

#include <nuttx/arch.h>
#include <nuttx/irq.h>

#include "arm64_arch.h"
#include "arm64_internal.h"

#ifndef CONFIG_DEV_SIMPLE_ADDRENV

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* PAR_EL1, Physical Address Register. Bit 0 reports a failed translation;
* on success bits [51:12] carry the physical frame.
*/

#define PAR_F (1ull << 0)
#define PAR_PA_MASK (0x000ffffffffff000ull)
#define VA_PAGE_OFFSET_MASK (0xfffull)

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: up_addrenv_va_to_pa
*
* Description:
* Map a virtual address to its physical address.
*
* The translation is asked of the MMU 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.
*
* Input Parameters:
* va - The virtual address to be mapped.
*
* Returned Value:
* Physical address on success; zero if the address is not mapped for a
* privileged read.
*
****************************************************************************/

uintptr_t up_addrenv_va_to_pa(void *va)
{
irqstate_t flags;
uint64_t par;

/* PAR_EL1 is a single register per CPU, so nothing may run between the
* translation and reading the result or it reads someone else's answer.
* Interrupts are banked with it, so masking them locally is enough.
*/

flags = up_irq_save();

__asm__ volatile ("at s1e1r, %0" : : "r" (va) : "memory");
UP_ISB();
par = read_sysreg(par_el1);

up_irq_restore(flags);

if ((par & PAR_F) != 0)
{
return 0;
}

return (uintptr_t)((par & PAR_PA_MASK) |
((uintptr_t)va & VA_PAGE_OFFSET_MASK));
}

#endif /* CONFIG_DEV_SIMPLE_ADDRENV */
10 changes: 9 additions & 1 deletion arch/arm64/src/imx9/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,15 @@ if(CONFIG_IMX9_FLEXSPI_NOR)
endif()

if(CONFIG_IMX9_BOOTLOADER)
list(APPEND SRCS imx9_system_ctl.c imx9_trdc.c imx9_ele.c)
list(APPEND SRCS imx9_system_ctl.c imx9_trdc.c)
endif()

if(CONFIG_IMX9_ELE)
list(APPEND SRCS imx9_ele.c)
endif()

if(CONFIG_IMX9_RNG)
list(APPEND SRCS imx9_rng.c)
endif()

if(CONFIG_IMX9_ROMAPI)
Expand Down
15 changes: 15 additions & 0 deletions arch/arm64/src/imx9/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ config IMX9_BOOTLOADER
bool "Bootloader"
select ARM64_DECODEFIQ if ARCH_ARM64_EXCEPTION_LEVEL = 3
select IMX9_DDR_TRAINING if ARCH_ARM64_EXCEPTION_LEVEL = 3
select IMX9_ELE
Comment thread
xiaoxiang781216 marked this conversation as resolved.
default n
---help---
Configure NuttX as the bootloader. NuttX will be compiled
Expand Down Expand Up @@ -125,8 +126,22 @@ config IMX_AHAB_CNTR_ADDR
---help---
Physical address where the AHAB container header is loaded into memory.

config IMX9_ELE
bool
default n

menu "i.MX9 Peripheral Selection"

config IMX9_RNG
bool "ELE true random number generator"
default n
select IMX9_ELE
select ARCH_HAVE_RNG
---help---
Register /dev/random and /dev/urandom, both backed by the ELE
true random number generator. Without this the entropy pool is
never seeded from hardware.

config IMX9_EDMA
bool "eDMA"
default n
Expand Down
7 changes: 7 additions & 0 deletions arch/arm64/src/imx9/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,16 @@ endif
ifeq ($(CONFIG_IMX9_BOOTLOADER),y)
CHIP_CSRCS += imx9_system_ctl.c
CHIP_CSRCS += imx9_trdc.c
endif

ifeq ($(CONFIG_IMX9_ELE),y)
CHIP_CSRCS += imx9_ele.c
endif

ifeq ($(CONFIG_IMX9_RNG),y)
CHIP_CSRCS += imx9_rng.c
endif

ifeq ($(CONFIG_IMX9_ROMAPI),y)
CHIP_CSRCS += imx9_romapi.c
endif
Comment thread
xiaoxiang781216 marked this conversation as resolved.
Expand Down
82 changes: 71 additions & 11 deletions arch/arm64/src/imx9/imx9_ele.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Included Files
****************************************************************************/

#include <nuttx/arch.h>
#include <nuttx/debug.h>
#include <errno.h>

Expand Down Expand Up @@ -146,6 +147,30 @@
}
}

/****************************************************************************
* Name: imx9_ele_buffer_pa
*
* Description:
* Physical address of a buffer the ELE will read or write. The enclave
* addresses memory physically while cache maintenance takes the virtual
* address, so a caller holding one of them cannot supply the other.
*
* Returned Value:
* The physical address, or zero if the buffer is not mapped.
*
****************************************************************************/

static uintptr_t imx9_ele_buffer_pa(void *va)
{
#ifdef CONFIG_ARCH_USE_MMU
return up_addrenv_va_to_pa(va);
#else
/* Without translation the virtual address is the physical one. */

return (uintptr_t)va;
#endif
}

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -199,6 +224,9 @@
int imx9_ele_get_key(uint8_t *key, size_t key_size,
uint8_t *ctx, size_t ctx_size)
{
uintptr_t key_pa;
uintptr_t ctx_pa;

if (!key)
{
_err("Invalid key parameter\n");
Expand Down Expand Up @@ -229,18 +257,27 @@
return -EINVAL;
}

key_pa = imx9_ele_buffer_pa(key);
ctx_pa = imx9_ele_buffer_pa(ctx);

if (key_pa == 0 || ctx_pa == 0)
{
_err("Buffer is not mapped\n");
return -EFAULT;
}

msg.header.version = ELE_VERSION;
msg.header.tag = ELE_CMD_TAG;
msg.header.size = 7;
msg.header.command = ELE_DERIVE_KEY_REQ;
msg.data[0] = upper_32_bits((ulong)key);
msg.data[1] = lower_32_bits((ulong)key);
msg.data[2] = upper_32_bits((ulong)ctx);
msg.data[3] = lower_32_bits((ulong)ctx);
msg.data[0] = upper_32_bits((ulong)key_pa);
msg.data[1] = lower_32_bits((ulong)key_pa);
msg.data[2] = upper_32_bits((ulong)ctx_pa);
msg.data[3] = lower_32_bits((ulong)ctx_pa);
msg.data[4] = ((ctx_size << 16) | key_size);

uint32_t crc = msg.header.data;
for (uint32_t i = 0; i < msg.header.size - 2; i++)

Check failure on line 280 in arch/arm64/src/imx9/imx9_ele.c

View workflow job for this annotation

GitHub Actions / check

Missing blank line after declarations
{
crc ^= msg.data[i];
}
Expand Down Expand Up @@ -424,7 +461,7 @@
{
struct ele_trng_state *ele_trng =
(struct ele_trng_state *)(msg.data + 1);
if (ele_trng->trng_state != ELE_TRNG_STATUS_READY ||

Check failure on line 464 in arch/arm64/src/imx9/imx9_ele.c

View workflow job for this annotation

GitHub Actions / check

Missing blank line after declarations
ele_trng->csal_state != ELE_CSAL_STATUS_READY)
{
/* Ensure imx9_ele_start_rng() was called earlier or we will
Expand All @@ -442,17 +479,39 @@
return -EIO;
}

int imx9_ele_get_random(uint32_t paddr, size_t len)
int imx9_ele_get_random(void *buf, size_t len)
{
uint16_t counter = 0;
uint16_t max_tries = ELE_RNG_TIMEOUT_US / ELE_RNG_SLEEP_US;
uintptr_t paddr;

if (paddr == 0 || len == 0)
if (buf == NULL || len == 0)
{
_err("Wrong input parameters!\n");
return -EINVAL;
}

/* The buffer is invalidated after the transfer, so anything sharing its
* first or last cache line would lose whatever was written meanwhile.
*/

if (!IS_ALIGNED((uintptr_t)buf, ARMV8A_DCACHE_LINESIZE) ||
!IS_ALIGNED(len, ARMV8A_DCACHE_LINESIZE))
{
_err("Buffer is not a whole number of cache lines\n");
return -EINVAL;
}

paddr = imx9_ele_buffer_pa(buf);

/* The address travels in a single 32-bit message word. */

if (paddr == 0 || paddr > UINT32_MAX - len)
{
_err("Buffer is not mapped, or is beyond the ELE address range\n");
return -EFAULT;
}

while ((imx9_ele_get_trng_state() != 0))
{
if (counter > max_tries)
Expand All @@ -465,16 +524,18 @@
counter++;
}

/* Flush the cache before sending the request to ELE. */
/* Cache maintenance takes the virtual address; the ELE takes the
* physical one.
*/

up_flush_dcache((uintptr_t)paddr, (uintptr_t)(paddr + len));
up_flush_dcache((uintptr_t)buf, (uintptr_t)buf + len);

msg.header.version = ELE_VERSION_FW;
msg.header.tag = ELE_CMD_TAG;
msg.header.size = 4;
msg.header.command = ELE_GET_RNG_REQ;
msg.data[0] = 0;
msg.data[1] = paddr;
msg.data[1] = (uint32_t)paddr;
msg.data[2] = len;

imx9_ele_sendmsg(&msg);
Expand All @@ -484,8 +545,7 @@
{
/* Invalidate the cache so we can read the result from RAM. */

up_invalidate_dcache((uintptr_t)paddr,
(uintptr_t)(paddr + len));
up_invalidate_dcache((uintptr_t)buf, (uintptr_t)buf + len);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/src/imx9/imx9_ele.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ int imx9_ele_get_trng_state(void);
*
****************************************************************************/

int imx9_ele_get_random(uint32_t paddr, size_t len);
int imx9_ele_get_random(void *buf, size_t len);

/****************************************************************************
* Name: imx9_ele_commit
Expand Down
Loading
Loading