DPDK logo

Elixir Cross Referencer

/*-
 * This file is provided under a dual BSD/GPLv2 license. When using or
 * redistributing this file, you may do so under either license.
 *
 *   BSD LICENSE
 *
 * Copyright 2008-2016 Freescale Semiconductor Inc.
 * Copyright (c) 2016 NXP.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the above-listed copyright holders nor the
 * names of any contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 *   GPL LICENSE SUMMARY
 *
 * ALTERNATIVELY, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") as published by the Free Software
 * Foundation, either version 2 of that License or (at your option) any
 * later version.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __RTA_STORE_CMD_H__
#define __RTA_STORE_CMD_H__

extern enum rta_sec_era rta_sec_era;

static const uint32_t store_src_table[][2] = {
/*1*/	{ KEY1SZ,       LDST_CLASS_1_CCB | LDST_SRCDST_WORD_KEYSZ_REG },
	{ KEY2SZ,       LDST_CLASS_2_CCB | LDST_SRCDST_WORD_KEYSZ_REG },
	{ DJQDA,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_JQDAR },
	{ MODE1,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_MODE_REG },
	{ MODE2,        LDST_CLASS_2_CCB | LDST_SRCDST_WORD_MODE_REG },
	{ DJQCTRL,      LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_JQCTRL },
	{ DATA1SZ,      LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DATASZ_REG },
	{ DATA2SZ,      LDST_CLASS_2_CCB | LDST_SRCDST_WORD_DATASZ_REG },
	{ DSTAT,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_STAT },
	{ ICV1SZ,       LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ICVSZ_REG },
	{ ICV2SZ,       LDST_CLASS_2_CCB | LDST_SRCDST_WORD_ICVSZ_REG },
	{ DPID,         LDST_CLASS_DECO | LDST_SRCDST_WORD_PID },
	{ CCTRL,        LDST_SRCDST_WORD_CHACTRL },
	{ ICTRL,        LDST_SRCDST_WORD_IRQCTRL },
	{ CLRW,         LDST_SRCDST_WORD_CLRW },
	{ MATH0,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH0 },
	{ CSTAT,        LDST_SRCDST_WORD_STAT },
	{ MATH1,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH1 },
	{ MATH2,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH2 },
	{ AAD1SZ,       LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DECO_AAD_SZ },
	{ MATH3,        LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH3 },
	{ IV1SZ,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_CLASS1_IV_SZ },
	{ PKASZ,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_A_SZ },
	{ PKBSZ,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_B_SZ },
	{ PKESZ,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_E_SZ },
	{ PKNSZ,        LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_N_SZ },
	{ CONTEXT1,     LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT },
	{ CONTEXT2,     LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT },
	{ DESCBUF,      LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF },
/*30*/	{ JOBDESCBUF,   LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF_JOB },
	{ SHAREDESCBUF, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF_SHARED },
/*32*/	{ JOBDESCBUF_EFF,   LDST_CLASS_DECO |
		LDST_SRCDST_WORD_DESCBUF_JOB_WE },
	{ SHAREDESCBUF_EFF, LDST_CLASS_DECO |
		LDST_SRCDST_WORD_DESCBUF_SHARED_WE },
/*34*/	{ GTR,          LDST_CLASS_DECO | LDST_SRCDST_WORD_GTR },
	{ STR,          LDST_CLASS_DECO | LDST_SRCDST_WORD_STR }
};

/*
 * Allowed STORE sources for each SEC ERA.
 * Values represent the number of entries from source_src_table[] that are
 * supported.
 */
static const unsigned int store_src_table_sz[] = {29, 31, 33, 33,
						  33, 33, 35, 35};

static inline int
rta_store(struct program *program, uint64_t src,
	  uint16_t offset, uint64_t dst, uint32_t length,
	  uint32_t flags)
{
	uint32_t opcode = 0, val;
	int ret = -EINVAL;
	unsigned int start_pc = program->current_pc;

	if (flags & SEQ)
		opcode = CMD_SEQ_STORE;
	else
		opcode = CMD_STORE;

	/* parameters check */
	if ((flags & IMMED) && (flags & SGF)) {
		pr_err("STORE: Invalid flag. SEC PC: %d; Instr: %d\n",
		       program->current_pc, program->current_instruction);
		goto err;
	}
	if ((flags & IMMED) && (offset != 0)) {
		pr_err("STORE: Invalid flag. SEC PC: %d; Instr: %d\n",
		       program->current_pc, program->current_instruction);
		goto err;
	}

	if ((flags & SEQ) && ((src == JOBDESCBUF) || (src == SHAREDESCBUF) ||
			      (src == JOBDESCBUF_EFF) ||
			      (src == SHAREDESCBUF_EFF))) {
		pr_err("STORE: Invalid SRC type. SEC PC: %d; Instr: %d\n",
		       program->current_pc, program->current_instruction);
		goto err;
	}

	if (flags & IMMED)
		opcode |= LDST_IMM;

	if ((flags & SGF) || (flags & VLF))
		opcode |= LDST_VLF;

	/*
	 * source for data to be stored can be specified as:
	 *    - register location; set in src field[9-15];
	 *    - if IMMED flag is set, data is set in value field [0-31];
	 *      user can give this value as actual value or pointer to data
	 */
	if (!(flags & IMMED)) {
		ret = __rta_map_opcode((uint32_t)src, store_src_table,
				       store_src_table_sz[rta_sec_era], &val);
		if (ret < 0) {
			pr_err("STORE: Invalid source. SEC PC: %d; Instr: %d\n",
			       program->current_pc,
			       program->current_instruction);
			goto err;
		}
		opcode |= val;
	}

	/* DESC BUFFER: length / offset values are specified in 4-byte words */
	if ((src == DESCBUF) || (src == JOBDESCBUF) || (src == SHAREDESCBUF) ||
	    (src == JOBDESCBUF_EFF) || (src == SHAREDESCBUF_EFF)) {
		opcode |= (length >> 2);
		opcode |= (uint32_t)((offset >> 2) << LDST_OFFSET_SHIFT);
	} else {
		opcode |= length;
		opcode |= (uint32_t)(offset << LDST_OFFSET_SHIFT);
	}

	__rta_out32(program, opcode);
	program->current_instruction++;

	if ((src == JOBDESCBUF) || (src == SHAREDESCBUF) ||
	    (src == JOBDESCBUF_EFF) || (src == SHAREDESCBUF_EFF))
		return (int)start_pc;

	/* for STORE, a pointer to where the data will be stored if needed */
	if (!(flags & SEQ))
		__rta_out64(program, program->ps, dst);

	/* for IMMED data, place the data here */
	if (flags & IMMED)
		__rta_inline_data(program, src, flags & __COPY_MASK, length);

	return (int)start_pc;

 err:
	program->first_error_pc = start_pc;
	program->current_instruction++;
	return ret;
}

#endif /* __RTA_STORE_CMD_H__ */