Skip to content

Commit

Permalink
nrf_security: drivers: cracen: make sx_*pkmem*() writes word-aligned
Browse files Browse the repository at this point in the history
Make the sx_*pkmem*() functions perform word-aligned and word-sized writes.
This is to work around a current limitation of CRACEN memory on certain
IP versions.

ref: DLT-3873
Signed-off-by: Tomi Fontanilles <[email protected]>
  • Loading branch information
tomi-font committed Jan 3, 2025
1 parent e430917 commit 07ab575
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef IOMEM_HEADER_FILE
#define IOMEM_HEADER_FILE

#include <string.h>

#ifdef SX_INSTRUMENT_MMIO_WITH_PRINTFS
#define SX_WARN_UNALIGNED_ADDR(addr) printk("%s: WARNING: unaligned address %p\r\n", __func__, addr)
#else
Expand Down Expand Up @@ -44,11 +46,7 @@ void sx_wrpkmem(void *dst, const void *src, size_t sz);
* Will be modified after this call
* @param[in] input_byte The byte value to be written.
*/
static inline void sx_wrpkmem_byte(void *dst, char input_byte)
{
volatile char *d = (volatile char *)dst;
*d = input_byte;
}
void sx_wrpkmem_byte(void *dst, char input_byte);

/** Read from device memory at src into normal memory at dst.
*
Expand All @@ -60,7 +58,10 @@ static inline void sx_wrpkmem_byte(void *dst, char input_byte)
* @param[in] src Source of read operation
* @param[in] sz The number of bytes to read from src to dst
*/
void sx_rdpkmem(void *dst, const void *src, size_t sz);
static inline void sx_rdpkmem(void *dst, const void *src, size_t sz)
{
memcpy(dst, src, sz);
}

/** Read a byte from device memory at src.
*
Expand Down
107 changes: 61 additions & 46 deletions subsys/nrf_security/src/drivers/cracen/silexpk/src/iomem.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,68 +18,83 @@
#define IS_NATURAL_SIZE(sz, type) 1
#endif

void sx_clrpkmem(void *dst, size_t sz)
static void write_incomplete_word(uint32_t *dst, const uint8_t *bytes,
size_t first_byte_pos, size_t num_bytes)
{
typedef int64_t clrblk_t;
volatile char *d = (volatile char *)dst;
if ((uintptr_t)dst % 4) {
SX_WARN_UNALIGNED_ADDR(dst);
}
uint32_t word = *dst;

for (size_t i = 0; i != num_bytes; ++i) {
((uint8_t *)&word)[first_byte_pos + i] = bytes[i];
}

#ifdef SX_INSTRUMENT_MMIO_WITH_PRINTFS
printk("write_incomplete_word(%p, 0x%x, %zu, %zu): 0x%x to 0x%x\r\n",
dst, *(uint32_t *)bytes, first_byte_pos, num_bytes, *dst, word);
#endif

*dst = word;
}

void sx_clrpkmem(void *dst, size_t sz)
{
if (sz == 0) {
return;
}

while (sz && (!IS_NATURAL_ALIGNED(d, clrblk_t))) {
*d = 0;
d++;
sz--;
#ifdef SX_INSTRUMENT_MMIO_WITH_PRINTFS
printk("sx_clrpkmem(%p, %zu)\r\n", dst, sz);
#endif
if ((uintptr_t)dst % 4) {
SX_WARN_UNALIGNED_ADDR(dst);
}
uint32_t *word_dst = (uint32_t *)dst;

#if !defined(__aarch64__)
memset((char *)d, 0, MASK_TO_NATURAL_SIZE(sz, clrblk_t));
d += MASK_TO_NATURAL_SIZE(sz, clrblk_t);
sz -= MASK_TO_NATURAL_SIZE(sz, clrblk_t);
for (size_t i = 0; i != sz / 4; ++i) {
word_dst[i] = 0;
}
if (sz % 4) {
uint32_t zero = 0;

#endif
while (sz) {
*d = 0;
d++;
sz--;
write_incomplete_word(&word_dst[sz / 4], (uint8_t *)&zero, 0, sz % 4);
}
}

struct uchunk {
int64_t a[2];
};

typedef struct uchunk tfrblk;
#define tfrblksz sizeof(tfrblk)

void sx_wrpkmem(void *dst, const void *src, size_t sz)
{
volatile char *d = (volatile char *)dst;
volatile const char *s = (volatile const char *)src;

while (sz && (!IS_NATURAL_ALIGNED(d, tfrblk) || !IS_NATURAL_SIZE(sz, tfrblk))) {
*d = *s;
d++;
s++;
sz--;
#ifdef SX_INSTRUMENT_MMIO_WITH_PRINTFS
printk("sx_wrpkmem(%p, %zu)\r\n", dst, sz);
#endif
uintptr_t dst_addr = (uintptr_t)dst;

if (dst_addr % 4) {
const size_t byte_count = 4 - dst_addr % 4;

write_incomplete_word((uint32_t *)(dst_addr & ~3), src, dst_addr % 4, byte_count);
*(uint8_t **)&dst += byte_count;
*(uint8_t **)&src += byte_count;
sz -= byte_count;
}

for (size_t i = 0; i != sz / 4; ++i) {
((uint32_t *)dst)[i] = ((uint32_t *)src)[i];
}

if (sz % 4) {
write_incomplete_word((uint32_t *)(dst_addr + (sz & ~3)),
(uint8_t *)src + (sz & ~3), 0, sz % 4);
}
memcpy((char *)d, (char *)s, sz);
}

void sx_rdpkmem(void *dst, const void *src, size_t sz)
void sx_wrpkmem_byte(void *dst, char input_byte)
{
if (IS_SAME_ALIGNMENT(dst, src, tfrblk) && IS_NATURAL_SIZE(sz, tfrblk)) {
memcpy(dst, src, sz);
} else {
volatile char *d = (volatile char *)dst;
volatile const char *s = (volatile const char *)src;

while (sz) {
*d = *s;
d++;
s++;
sz--;
}
}
uintptr_t dst_addr = (uintptr_t)dst;
uint32_t *word_dst = (uint32_t *)(dst_addr & ~3);
uint32_t word = *word_dst;
size_t byte_index = dst_addr % 4;

((uint8_t *)&word)[byte_index] = input_byte;
*word_dst = word;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#ifndef PKHARDWARE_BA414E_H
#define PKHARDWARE_BA414E_H

#include <silexpk/core.h>
#include <stdint.h>

struct sx_pk_cmd_def {
Expand Down

0 comments on commit 07ab575

Please sign in to comment.