Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 261ea058 authored by Horia Geantă's avatar Horia Geantă Committed by Herbert Xu
Browse files

crypto: caam - handle core endianness != caam endianness



There are SoCs like LS1043A where CAAM endianness (BE) does not match
the default endianness of the core (LE).
Moreover, there are requirements for the driver to handle cases like
CPU_BIG_ENDIAN=y on ARM-based SoCs.
This requires for a complete rewrite of the I/O accessors.

PPC-specific accessors - {in,out}_{le,be}XX - are replaced with
generic ones - io{read,write}[be]XX.

Endianness is detected dynamically (at runtime) to allow for
multiplatform kernels, for e.g. running the same kernel image
on LS1043A (BE CAAM) and LS2080A (LE CAAM) armv8-based SoCs.

While here: debugfs entries need to take into consideration the
endianness of the core when displaying data. Add the necessary
glue code so the entries remain the same, but they are properly
read, regardless of the core and/or SEC endianness.

Note: pdb.h fixes only what is currently being used (IPsec).

Reviewed-by: default avatarTudor Ambarus <tudor-dan.ambarus@nxp.com>
Signed-off-by: default avatarHoria Geantă <horia.geanta@nxp.com>
Signed-off-by: default avatarAlex Porosanu <alexandru.porosanu@nxp.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent bd52f1c2
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -116,10 +116,6 @@ config CRYPTO_DEV_FSL_CAAM_IMX
	def_bool SOC_IMX6 || SOC_IMX7D
	depends on CRYPTO_DEV_FSL_CAAM

config CRYPTO_DEV_FSL_CAAM_LE
	def_bool CRYPTO_DEV_FSL_CAAM_IMX || SOC_LS1021A
	depends on CRYPTO_DEV_FSL_CAAM

config CRYPTO_DEV_FSL_CAAM_DEBUG
	bool "Enable debug output in CAAM driver"
	depends on CRYPTO_DEV_FSL_CAAM
+3 −2
Original line number Diff line number Diff line
@@ -847,7 +847,7 @@ static int ahash_update_ctx(struct ahash_request *req)
							 *next_buflen, 0);
		} else {
			(edesc->sec4_sg + sec4_sg_src_index - 1)->len |=
							SEC4_SG_LEN_FIN;
				cpu_to_caam32(SEC4_SG_LEN_FIN);
		}

		state->current_buf = !state->current_buf;
@@ -949,7 +949,8 @@ static int ahash_final_ctx(struct ahash_request *req)
	state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
						buf, state->buf_dma, buflen,
						last_buflen);
	(edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN;
	(edesc->sec4_sg + sec4_sg_src_index - 1)->len |=
		cpu_to_caam32(SEC4_SG_LEN_FIN);

	edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
					    sec4_sg_bytes, DMA_TO_DEVICE);
+80 −45
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
#include "desc_constr.h"
#include "error.h"

bool caam_little_end;
EXPORT_SYMBOL(caam_little_end);

/*
 * i.MX targets tend to have clock control subsystems that can
 * enable/disable clocking to our device.
@@ -106,7 +109,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,


	if (ctrlpriv->virt_en == 1) {
		setbits32(&ctrl->deco_rsr, DECORSR_JR0);
		clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);

		while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) &&
		       --timeout)
@@ -115,7 +118,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
		timeout = 100000;
	}

	setbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
	clrsetbits_32(&ctrl->deco_rq, 0, DECORR_RQD0ENABLE);

	while (!(rd_reg32(&ctrl->deco_rq) & DECORR_DEN0) &&
								 --timeout)
@@ -123,12 +126,12 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,

	if (!timeout) {
		dev_err(ctrldev, "failed to acquire DECO 0\n");
		clrbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
		clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
		return -ENODEV;
	}

	for (i = 0; i < desc_len(desc); i++)
		wr_reg32(&deco->descbuf[i], *(desc + i));
		wr_reg32(&deco->descbuf[i], caam32_to_cpu(*(desc + i)));

	flags = DECO_JQCR_WHL;
	/*
@@ -139,7 +142,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
		flags |= DECO_JQCR_FOUR;

	/* Instruct the DECO to execute it */
	setbits32(&deco->jr_ctl_hi, flags);
	clrsetbits_32(&deco->jr_ctl_hi, 0, flags);

	timeout = 10000000;
	do {
@@ -158,10 +161,10 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
		  DECO_OP_STATUS_HI_ERR_MASK;

	if (ctrlpriv->virt_en == 1)
		clrbits32(&ctrl->deco_rsr, DECORSR_JR0);
		clrsetbits_32(&ctrl->deco_rsr, DECORSR_JR0, 0);

	/* Mark the DECO as free */
	clrbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
	clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);

	if (!timeout)
		return -EAGAIN;
@@ -349,7 +352,7 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
	r4tst = &ctrl->r4tst[0];

	/* put RNG4 into program mode */
	setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
	clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);

	/*
	 * Performance-wise, it does not make sense to
@@ -363,7 +366,7 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
	      >> RTSDCTL_ENT_DLY_SHIFT;
	if (ent_delay <= val) {
		/* put RNG4 into run mode */
		clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
		clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, 0);
		return;
	}

@@ -381,9 +384,9 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
	 * select raw sampling in both entropy shifter
	 * and statistical checker
	 */
	setbits32(&val, RTMCTL_SAMP_MODE_RAW_ES_SC);
	clrsetbits_32(&val, 0, RTMCTL_SAMP_MODE_RAW_ES_SC);
	/* put RNG4 into run mode */
	clrbits32(&val, RTMCTL_PRGM);
	clrsetbits_32(&val, RTMCTL_PRGM, 0);
	/* write back the control register */
	wr_reg32(&r4tst->rtmctl, val);
}
@@ -406,6 +409,23 @@ int caam_get_era(void)
}
EXPORT_SYMBOL(caam_get_era);

#ifdef CONFIG_DEBUG_FS
static int caam_debugfs_u64_get(void *data, u64 *val)
{
	*val = caam64_to_cpu(*(u64 *)data);
	return 0;
}

static int caam_debugfs_u32_get(void *data, u64 *val)
{
	*val = caam32_to_cpu(*(u32 *)data);
	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u32_ro, caam_debugfs_u32_get, NULL, "%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u64_ro, caam_debugfs_u64_get, NULL, "%llu\n");
#endif

/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
@@ -504,6 +524,10 @@ static int caam_probe(struct platform_device *pdev)
		ret = -ENOMEM;
		goto disable_caam_emi_slow;
	}

	caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) &
				  (CSTA_PLEND | CSTA_ALT_PLEND));

	/* Finding the page size for using the CTPR_MS register */
	comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms);
	pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT;
@@ -559,7 +583,7 @@ static int caam_probe(struct platform_device *pdev)
	}

	if (ctrlpriv->virt_en == 1)
		setbits32(&ctrl->jrstart, JRSTART_JR0_START |
		clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START |
			      JRSTART_JR1_START | JRSTART_JR2_START |
			      JRSTART_JR3_START);

@@ -693,7 +717,7 @@ static int caam_probe(struct platform_device *pdev)
		ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;

		/* Enable RDB bit so that RNG works faster */
		setbits32(&ctrl->scfgr, SCFGR_RDBENABLE);
		clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
	}

	/* NOTE: RTIC detection ought to go here, around Si time */
@@ -719,48 +743,59 @@ static int caam_probe(struct platform_device *pdev)
	ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root);

	/* Controller-level - performance monitor counters */

	ctrlpriv->ctl_rq_dequeued =
		debugfs_create_u64("rq_dequeued",
		debugfs_create_file("rq_dequeued",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->req_dequeued);
				    ctrlpriv->ctl, &perfmon->req_dequeued,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ob_enc_req =
		debugfs_create_u64("ob_rq_encrypted",
		debugfs_create_file("ob_rq_encrypted",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ob_enc_req);
				    ctrlpriv->ctl, &perfmon->ob_enc_req,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ib_dec_req =
		debugfs_create_u64("ib_rq_decrypted",
		debugfs_create_file("ib_rq_decrypted",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ib_dec_req);
				    ctrlpriv->ctl, &perfmon->ib_dec_req,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ob_enc_bytes =
		debugfs_create_u64("ob_bytes_encrypted",
		debugfs_create_file("ob_bytes_encrypted",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ob_enc_bytes);
				    ctrlpriv->ctl, &perfmon->ob_enc_bytes,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ob_prot_bytes =
		debugfs_create_u64("ob_bytes_protected",
		debugfs_create_file("ob_bytes_protected",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ob_prot_bytes);
				    ctrlpriv->ctl, &perfmon->ob_prot_bytes,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ib_dec_bytes =
		debugfs_create_u64("ib_bytes_decrypted",
		debugfs_create_file("ib_bytes_decrypted",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ib_dec_bytes);
				    ctrlpriv->ctl, &perfmon->ib_dec_bytes,
				    &caam_fops_u64_ro);
	ctrlpriv->ctl_ib_valid_bytes =
		debugfs_create_u64("ib_bytes_validated",
		debugfs_create_file("ib_bytes_validated",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->ib_valid_bytes);
				    ctrlpriv->ctl, &perfmon->ib_valid_bytes,
				    &caam_fops_u64_ro);

	/* Controller level - global status values */
	ctrlpriv->ctl_faultaddr =
		debugfs_create_u64("fault_addr",
		debugfs_create_file("fault_addr",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->faultaddr);
				    ctrlpriv->ctl, &perfmon->faultaddr,
				    &caam_fops_u32_ro);
	ctrlpriv->ctl_faultdetail =
		debugfs_create_u32("fault_detail",
		debugfs_create_file("fault_detail",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->faultdetail);
				    ctrlpriv->ctl, &perfmon->faultdetail,
				    &caam_fops_u32_ro);
	ctrlpriv->ctl_faultstatus =
		debugfs_create_u32("fault_status",
		debugfs_create_file("fault_status",
				    S_IRUSR | S_IRGRP | S_IROTH,
				   ctrlpriv->ctl, &perfmon->status);
				    ctrlpriv->ctl, &perfmon->status,
				    &caam_fops_u32_ro);

	/* Internal covering keys (useful in non-secure mode only) */
	ctrlpriv->ctl_kek_wrap.data = &ctrlpriv->ctrl->kek[0];
+3 −4
Original line number Diff line number Diff line
@@ -23,16 +23,15 @@
#define SEC4_SG_OFFSET_MASK	0x00001fff

struct sec4_sg_entry {
#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
#if !defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) && \
	defined(CONFIG_CRYPTO_DEV_FSL_CAAM_IMX)
	u32 rsvd1;
	dma_addr_t ptr;
#else
	u64 ptr;
#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_IMX */
	u32 len;
	u8 rsvd2;
	u8 buf_pool_id;
	u16 offset;
	u32 bpid_offset;
};

/* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
+29 −15
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 */

#include "desc.h"
#include "regs.h"

#define IMMEDIATE (1 << 23)
#define CAAM_CMD_SZ sizeof(u32)
@@ -30,9 +31,11 @@
			       LDST_SRCDST_WORD_DECOCTRL | \
			       (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))

extern bool caam_little_end;

static inline int desc_len(u32 *desc)
{
	return *desc & HDR_DESCLEN_MASK;
	return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK;
}

static inline int desc_bytes(void *desc)
@@ -52,7 +55,7 @@ static inline void *sh_desc_pdb(u32 *desc)

static inline void init_desc(u32 *desc, u32 options)
{
	*desc = (options | HDR_ONE) + 1;
	*desc = cpu_to_caam32((options | HDR_ONE) + 1);
}

static inline void init_sh_desc(u32 *desc, u32 options)
@@ -78,9 +81,10 @@ static inline void append_ptr(u32 *desc, dma_addr_t ptr)
{
	dma_addr_t *offset = (dma_addr_t *)desc_end(desc);

	*offset = ptr;
	*offset = cpu_to_caam_dma(ptr);

	(*desc) += CAAM_PTR_SZ / CAAM_CMD_SZ;
	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
				CAAM_PTR_SZ / CAAM_CMD_SZ);
}

static inline void init_job_desc_shared(u32 *desc, dma_addr_t ptr, int len,
@@ -99,16 +103,17 @@ static inline void append_data(u32 *desc, void *data, int len)
	if (len) /* avoid sparse warning: memcpy with byte count of 0 */
		memcpy(offset, data, len);

	(*desc) += (len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
				(len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ);
}

static inline void append_cmd(u32 *desc, u32 command)
{
	u32 *cmd = desc_end(desc);

	*cmd = command;
	*cmd = cpu_to_caam32(command);

	(*desc)++;
	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 1);
}

#define append_u32 append_cmd
@@ -117,16 +122,22 @@ static inline void append_u64(u32 *desc, u64 data)
{
	u32 *offset = desc_end(desc);

	*offset = upper_32_bits(data);
	*(++offset) = lower_32_bits(data);
	/* Only 32-bit alignment is guaranteed in descriptor buffer */
	if (caam_little_end) {
		*offset = cpu_to_caam32(lower_32_bits(data));
		*(++offset) = cpu_to_caam32(upper_32_bits(data));
	} else {
		*offset = cpu_to_caam32(upper_32_bits(data));
		*(++offset) = cpu_to_caam32(lower_32_bits(data));
	}

	(*desc) += 2;
	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 2);
}

/* Write command without affecting header, and return pointer to next word */
static inline u32 *write_cmd(u32 *desc, u32 command)
{
	*desc = command;
	*desc = cpu_to_caam32(command);

	return desc + 1;
}
@@ -168,14 +179,17 @@ APPEND_CMD_RET(move, MOVE)

static inline void set_jump_tgt_here(u32 *desc, u32 *jump_cmd)
{
	*jump_cmd = *jump_cmd | (desc_len(desc) - (jump_cmd - desc));
	*jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) |
				  (desc_len(desc) - (jump_cmd - desc)));
}

static inline void set_move_tgt_here(u32 *desc, u32 *move_cmd)
{
	*move_cmd &= ~MOVE_OFFSET_MASK;
	*move_cmd = *move_cmd | ((desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) &
				 MOVE_OFFSET_MASK);
	u32 val = caam32_to_cpu(*move_cmd);

	val &= ~MOVE_OFFSET_MASK;
	val |= (desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) & MOVE_OFFSET_MASK;
	*move_cmd = cpu_to_caam32(val);
}

#define APPEND_CMD(cmd, op) \
Loading