/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright(c) 2007-2022 Intel Corporation */
/**
 ***************************************************************************
 * @file lac_mem.h
 *
 * @defgroup LacMem     Memory
 *
 * @ingroup LacCommon
 *
 * Memory re-sizing functions and memory accessor macros.
 *
 ***************************************************************************/

#ifndef LAC_MEM_H
#define LAC_MEM_H

/***************************************************************************
 * Include header files
 ***************************************************************************/
#include "cpa.h"
#include "qat_utils.h"
#include "lac_common.h"

/**
 *******************************************************************************
 * @ingroup LacMem
 *      These macros are used to Endian swap variables from IA to QAT.
 *
 * @param[out] x    The variable to be swapped.
 *
 * @retval none
 ******************************************************************************/
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define LAC_MEM_WR_64(x) QAT_UTILS_HOST_TO_NW_64(x)
#define LAC_MEM_WR_32(x) QAT_UTILS_HOST_TO_NW_32(x)
#define LAC_MEM_WR_16(x) QAT_UTILS_HOST_TO_NW_16(x)
#define LAC_MEM_RD_64(x) QAT_UTILS_NW_TO_HOST_64(x)
#define LAC_MEM_RD_32(x) QAT_UTILS_NW_TO_HOST_32(x)
#define LAC_MEM_RD_16(x) QAT_UTILS_NW_TO_HOST_16(x)
#else
#define LAC_MEM_WR_64(x) (x)
#define LAC_MEM_WR_32(x) (x)
#define LAC_MEM_WR_16(x) (x)
#define LAC_MEM_RD_64(x) (x)
#define LAC_MEM_RD_32(x) (x)
#define LAC_MEM_RD_16(x) (x)
#endif

/*
*******************************************************************************
* Shared Memory Macros (memory accessible by Acceleration Engines, e.g. QAT)
*******************************************************************************
*/

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to write to a variable that will be read by the
 * QAT. The macro will automatically detect the size of the target variable and
 * will select the correct method for performing the write. The data is cast to
 * the type of the field that it will be written to.
 * This macro swaps data if required.
 *
 * @param[out] var    The variable to be written. Can be a field of a struct.
 *
 * @param[in] data    The value to be written.  Will be cast to the size of the
 *                    target.
 *
 * @retval none
 ******************************************************************************/
#define LAC_MEM_SHARED_WRITE_SWAP(var, data)                                   \
	do {                                                                   \
		switch (sizeof(var)) {                                         \
		case 1:                                                        \
			(var) = (Cpa8U)(data);                                 \
			break;                                                 \
		case 2:                                                        \
			(var) = (Cpa16U)(data);                                \
			(var) = LAC_MEM_WR_16(((Cpa16U)var));                  \
			break;                                                 \
		case 4:                                                        \
			(var) = (Cpa32U)(data);                                \
			(var) = LAC_MEM_WR_32(((Cpa32U)var));                  \
			break;                                                 \
		case 8:                                                        \
			(var) = (Cpa64U)(data);                                \
			(var) = LAC_MEM_WR_64(((Cpa64U)var));                  \
			break;                                                 \
		default:                                                       \
			break;                                                 \
		}                                                              \
	} while (0)

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to read a variable that was written by the QAT.
 * The macro will automatically detect the size of the data to be read and will
 * select the correct method for performing the read. The value read from the
 * variable is cast to the size of the data type it will be stored in.
 * This macro swaps data if required.
 *
 * @param[in] var     The variable to be read. Can be a field of a struct.
 *
 * @param[out] data   The variable to hold the result of the read. Data read
 *                    will be cast to the size of this variable
 *
 * @retval none
 ******************************************************************************/
#define LAC_MEM_SHARED_READ_SWAP(var, data)                                    \
	do {                                                                   \
		switch (sizeof(var)) {                                         \
		case 1:                                                        \
			(data) = (var);                                        \
			break;                                                 \
		case 2:                                                        \
			(data) = LAC_MEM_RD_16(((Cpa16U)var));                 \
			break;                                                 \
		case 4:                                                        \
			(data) = LAC_MEM_RD_32(((Cpa32U)var));                 \
			break;                                                 \
		case 8:                                                        \
			(data) = LAC_MEM_RD_64(((Cpa64U)var));                 \
			break;                                                 \
		default:                                                       \
			break;                                                 \
		}                                                              \
	} while (0)

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to write a pointer to a QAT request. The fields
 *      for pointers in the QAT request and response messages are always 64 bits
 *
 * @param[out] var    The variable to be written to. Can be a field of a struct.
 *
 * @param[in] data    The value to be written.  Will be cast to size of target
 *                    variable
 *
 * @retval none
 ******************************************************************************/
/* cast pointer to scalar of same size of the native pointer */
#define LAC_MEM_SHARED_WRITE_FROM_PTR(var, data)                               \
	((var) = (Cpa64U)(LAC_ARCH_UINT)(data))

/* Note: any changes to this macro implementation should also be made to the
 * similar LAC_MEM_CAST_PTR_TO_UINT64 macro
 */

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to read a pointer from a QAT response. The fields
 *      for pointers in the QAT request and response messages are always 64 bits
 *
 * @param[in] var     The variable to be read. Can be a field of a struct.
 *
 * @param[out] data   The variable to hold the result of the read. Data read
 *                    will be cast to the size of this variable
 *
 * @retval none
 ******************************************************************************/
/* Cast back to native pointer */
#define LAC_MEM_SHARED_READ_TO_PTR(var, data)                                  \
	((data) = (void *)(LAC_ARCH_UINT)(var))

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro safely casts a pointer to a Cpa64U type.
 *
 * @param[in] pPtr   The pointer to be cast.
 *
 * @retval pointer cast to Cpa64U
 ******************************************************************************/
#define LAC_MEM_CAST_PTR_TO_UINT64(pPtr) ((Cpa64U)(pPtr))

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro uses an QAT Utils macro to convert from a virtual address to
 *a
 *      physical address for internally allocated memory.
 *
 * @param[in] pVirtAddr   The address to be converted.
 *
 * @retval The converted physical address
 ******************************************************************************/
#define LAC_OS_VIRT_TO_PHYS_INTERNAL(pVirtAddr)                                \
	(QAT_UTILS_MMU_VIRT_TO_PHYS(pVirtAddr))

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro should be called on all externally allocated memory it calls
 *      SalMem_virt2PhysExternal function which allows a user
 *      to set the virt2phys function used by an instance.
 *      Defaults to virt to phys for kernel.
 *
 * @param[in] genService  Generic sal_service_t structure.
 * @param[in] pVirtAddr   The address to be converted.
 *
 * @retval The converted physical address
 ******************************************************************************/
#define LAC_OS_VIRT_TO_PHYS_EXTERNAL(genService, pVirtAddr)                    \
	((SalMem_virt2PhysExternal(pVirtAddr, &(genService))))

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to write an address variable that will be read by
 * the QAT.  The macro will perform the necessary virt2phys address translation
 * This macro is only to be called on memory allocated internally by the driver.
 *
 * @param[out] var  The address variable to write. Can be a field of a struct.
 *
 * @param[in] pPtr  The pointer variable to containing the address to be
 *                  written
 *
 * @retval none
 ******************************************************************************/
#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_INTERNAL(var, pPtr)              \
	do {                                                                   \
		Cpa64U physAddr = 0;                                           \
		physAddr = LAC_MEM_CAST_PTR_TO_UINT64(                         \
		    LAC_OS_VIRT_TO_PHYS_INTERNAL(pPtr));                       \
		var = physAddr;                                                \
	} while (0)

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This macro can be used to write an address variable that will be read by
 * the QAT.  The macro will perform the necessary virt2phys address translation
 * This macro is to be used on memory allocated externally by the user. It calls
 * the user supplied virt2phys address translation.
 *
 * @param[in] pService The pointer to the service
 * @param[out] var     The address variable to write. Can be a field of a struct
 * @param[in] pPtr     The pointer variable to containing the address to be
 *                     written
 *
 * @retval none
 ******************************************************************************/
#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(pService, var, pPtr)    \
	do {                                                                   \
		Cpa64U physAddr = 0;                                           \
		physAddr = LAC_MEM_CAST_PTR_TO_UINT64(                         \
		    LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService, pPtr));             \
		var = physAddr;                                                \
	} while (0)

/*
*******************************************************************************
* OS Memory Macros
*******************************************************************************
*/

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This function and associated macro allocates the memory for the given
 *      size and stores the address of the memory allocated in the pointer.
 *
 * @param[out] ppMemAddr    address of pointer where address will be stored
 * @param[in] sizeBytes     the size of the memory to be allocated.
 *
 * @retval CPA_STATUS_RESOURCE  Macro failed to allocate Memory
 * @retval CPA_STATUS_SUCCESS   Macro executed successfully
 *
 ******************************************************************************/
static __inline CpaStatus
LacMem_OsMemAlloc(void **ppMemAddr, Cpa32U sizeBytes)
{
	*ppMemAddr = malloc(sizeBytes, M_QAT, M_WAITOK);

	return CPA_STATUS_SUCCESS;
}

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This function and associated macro allocates the contiguous
 *       memory for the given
 *      size and stores the address of the memory allocated in the pointer.
 *
 * @param[out] ppMemAddr     address of pointer where address will be stored
 * @param[in] sizeBytes      the size of the memory to be allocated.
 * @param[in] alignmentBytes the alignment
 * @param[in] node           node to allocate from
 *
 * @retval CPA_STATUS_RESOURCE  Macro failed to allocate Memory
 * @retval CPA_STATUS_SUCCESS   Macro executed successfully
 *
 ******************************************************************************/
static __inline CpaStatus
LacMem_OsContigAlignMemAlloc(void **ppMemAddr,
			     Cpa32U sizeBytes,
			     Cpa32U alignmentBytes,
			     Cpa32U node)
{
	if ((alignmentBytes & (alignmentBytes - 1)) !=
	    0) /* if is not power of 2 */
	{
		*ppMemAddr = NULL;
		QAT_UTILS_LOG("alignmentBytes MUST be the power of 2\n");
		return CPA_STATUS_INVALID_PARAM;
	}

	*ppMemAddr =
	    qatUtilsMemAllocContiguousNUMA(sizeBytes, node, alignmentBytes);

	if (NULL == *ppMemAddr) {
		return CPA_STATUS_RESOURCE;
	}

	return CPA_STATUS_SUCCESS;
}

/**
 *******************************************************************************
 * @ingroup LacMem
 *      Macro from the malloc() function
 *
 ******************************************************************************/
#define LAC_OS_MALLOC(sizeBytes) malloc(sizeBytes, M_QAT, M_WAITOK)

/**
 *******************************************************************************
 * @ingroup LacMem
 *      Macro from the LacMem_OsContigAlignMemAlloc function
 *
 ******************************************************************************/
#define LAC_OS_CAMALLOC(ppMemAddr, sizeBytes, alignmentBytes, node)            \
	LacMem_OsContigAlignMemAlloc((void *)ppMemAddr,                        \
				     sizeBytes,                                \
				     alignmentBytes,                           \
				     node)

/**
 *******************************************************************************
 * @ingroup LacMem
 *      Macro for declaration static const unsigned int constant. One provides
 *   the compilation time computation with the highest bit set in the
 *   sizeof(TYPE) value. The constant is being put by the linker by default in
 *   .rodata section
 *
 *   E.g. Statement LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t)
 *   results in following entry:
 *     static const unsigned int highest_bit_of_lac_mem_blk_t = 3
 *
 *   CAUTION!!
 *      Macro is prepared only for type names NOT-containing ANY
 *  special characters. Types as amongst others:
 *  - void *
 *  - unsigned long
 *  - unsigned int
 *  are strictly forbidden and will result in compilation error.
 *  Use typedef to provide one-word type name for MACRO's usage.
 ******************************************************************************/
#define LAC_DECLARE_HIGHEST_BIT_OF(TYPE)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \
	static const unsigned int highest_bit_of_##TYPE =                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      \
	    (sizeof(TYPE) & 0x80000000 ? 31 : (sizeof(TYPE) & 0x40000000 ? 30 : (sizeof(TYPE) & 0x20000000 ? 29 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            \
														      sizeof(TYPE) & 0x10000000 ? 28 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \
																			   sizeof(TYPE) & 0x08000000 ? 27 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  \
																								sizeof(TYPE) & 0x04000000 ? 26 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             \
																												     sizeof(TYPE) & 0x02000000 ? 25 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        \
																																	  sizeof(TYPE) & 0x01000000 ? 24 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   \
																																					       sizeof(TYPE) & 0x00800000 ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     \
																																						   23 :                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        \
																																						   (sizeof(TYPE) & 0x00400000 ? 22 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         \
																																											 sizeof(                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \
																																											     TYPE) &                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           \
																																												 0x00200000 ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  \
																																											     21 :                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              \
																																											     (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 \
																																												 sizeof(TYPE) & 0x00100000 ? 20 : (sizeof(TYPE) & 0x00080000 ? 19 : (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          \
																																																					sizeof(                                                                                                                                                                                                                                                                                                                                                                                                                                                                                \
																																																					    TYPE) &                                                                                                                                                                                                                                                                                                                                                                                                                                                                            \
																																																						0x00040000 ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                   \
																																																					    18 :                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \
																																																					    (                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  \
																																																						sizeof(TYPE) & 0x00020000 ? 17 : (                                                                                                                                                                                                                                                                                                                                                                                                                                             \
																																																										     sizeof(TYPE) & 0x00010000 ? 16 : (sizeof(TYPE) &                                                                                                                                                                                                                                                                                                                                                                                          \
																																																															       0x00008000 ?                                                                                                                                                                                                                                                                                                                                                                                    \
																																																															   15 :                                                                                                                                                                                                                                                                                                                                                                                                \
																																																															   (sizeof(TYPE) & 0x00004000 ? 14 : (                                                                                                                                                                                                                                                                                                                                                                 \
																																																																				 sizeof(TYPE) & 0x00002000 ? 13 :                                                                                                                                                                                                                                                                                                                              \
																																																																							     (                                                                                                                                                                                                                                                                                                                                 \
																																																																								 sizeof(TYPE) & 0x00001000 ? 12 : (                                                                                                                                                                                                                                                                                            \
																																																																												      sizeof(TYPE) & 0x00000800 ? 11 : (                                                                                                                                                                                                                                                       \
																																																																																	   sizeof(TYPE) & 0x00000400 ? 10 :                                                                                                                                                                                                                    \
																																																																																				       (                                                                                                                                                                                                                       \
																																																																																					   sizeof(TYPE) &                                                                                                                                                                                                      \
																																																																																						   0x00000200 ?                                                                                                                                                                                                \
																																																																																					       9 :                                                                                                                                                                                                             \
																																																																																					       (sizeof(                                                                                                                                                                                                        \
																																																																																						    TYPE) &                                                                                                                                                                                                    \
																																																																																							0x00000100 ?                                                                                                                                                                                           \
																																																																																						    8 :                                                                                                                                                                                                        \
																																																																																						    (sizeof(TYPE) & 0x00000080 ? 7 :                                                                                                                                                                           \
																																																																																										 (                                                                                                                                                                             \
																																																																																										     sizeof(TYPE) & 0x00000040 ?                                                                                                                                               \
																																																																																											 6 :                                                                                                                                                                   \
																																																																																											 (                                                                                                                                                                     \
																																																																																											     sizeof(TYPE) & 0x00000020 ? 5 :                                                                                                                                   \
																																																																																															 (                                                                                                                                     \
																																																																																															     sizeof(TYPE) & 0x00000010 ? 4 :                                                                                                   \
																																																																																																			 (                                                                                                     \
																																																																																																			     sizeof(TYPE) & 0x00000008 ? 3 :                                                                   \
																																																																																																							 (                                                                     \
																																																																																																							     sizeof(TYPE) & 0x00000004 ? 2 :                                   \
																																																																																																											 (                                     \
																																																																																																											     sizeof(TYPE) & 0x00000002 ? 1 : ( \
																																																																																																																 sizeof(TYPE) & 0x00000001 ? 0 : 32))))))))))))))))) /*16*/))))))))))))))) /* 31 */

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This function and associated macro frees the memory at the given address
 *      and resets the pointer to NULL
 *
 * @param[out] ppMemAddr    address of pointer where mem address is stored.
 *                          If pointer is NULL, the function will exit silently
 *
 * @retval void
 *
 ******************************************************************************/
static __inline void
LacMem_OsMemFree(void **ppMemAddr)
{
	free(*ppMemAddr, M_QAT);
	*ppMemAddr = NULL;
}

/**
 *******************************************************************************
 * @ingroup LacMem
 *      This function and associated macro frees the contiguous memory at the
 *      given address and resets the pointer to NULL
 *
 * @param[out] ppMemAddr    address of pointer where mem address is stored.
 *                          If pointer is NULL, the function will exit silently
 *
 * @retval void
 *
 ******************************************************************************/
static __inline void
LacMem_OsContigAlignMemFree(void **ppMemAddr)
{
	if (NULL != *ppMemAddr) {
		qatUtilsMemFreeNUMA(*ppMemAddr);
		*ppMemAddr = NULL;
	}
}

#define LAC_OS_FREE(pMemAddr) LacMem_OsMemFree((void *)&pMemAddr)

#define LAC_OS_CAFREE(pMemAddr) LacMem_OsContigAlignMemFree((void *)&pMemAddr)

/**
*******************************************************************************
 * @ingroup LacMem
 *     Copies user data to a working buffer of the correct size (required by
 *     PKE services)
 *
 * @description
 *      This function produces a correctly sized working buffer from the input
 *      user buffer. If the original buffer is too small a new buffer shall
 *      be allocated and memory is copied (left padded with zeros to the
*required
 *      length).
 *
 *      The returned working buffer is guaranteed to be of the desired size for
 *      QAT.
 *
 *      When this function is called pInternalMem describes the user_buffer and
 *      when the function returns pInternalMem describes the working buffer.
 *      This is because pInternalMem describes the memory that will be sent to
 *      QAT.
 *
 *      The caller must keep the original buffer pointer. The alllocated buffer
*is
 *      freed (as necessary) using icp_LacBufferRestore().
 *
 * @param[in] instanceHandle Handle to crypto instance so pke_resize mem pool
*can
 *                           be located
 * @param[in] pUserBuffer Pointer on the user buffer
 * @param[in] userLen     length of the user buffer
 * @param[in] workingLen  length of the working (correctly sized) buffer
 * @param[in/out] pInternalMem    pointer to boolean if TRUE on input then
 *                                user_buffer is internally allocated memory
 *                                if false then it is externally allocated.
 *                                This value gets updated by the function
 *                                if the returned pointer references internally
 *                                allocated memory.
 *
 * @return a pointer to the working (correctly sized) buffer or NULL if the
 *      allocation failed
 *
 * @note the working length cannot be smaller than the user buffer length
 *
 * @warning the working buffer may be the same or different from the original
 * user buffer; the caller should make no assumptions in this regard
 *
 * @see icp_LacBufferRestore()
 *
 ******************************************************************************/
Cpa8U *icp_LacBufferResize(CpaInstanceHandle instanceHandle,
			   Cpa8U *pUserBuffer,
			   Cpa32U userLen,
			   Cpa32U workingLen,
			   CpaBoolean *pInternalMemory);

/**
*******************************************************************************
 * @ingroup LacMem
 *     Restores a user buffer
 *
 * @description
 *      This function restores a user buffer and releases its
 *      corresponding working buffer. The working buffer, assumed to be
 *      previously obtained using icp_LacBufferResize(), is freed as necessary.
 *
 *      The contents are copied in the process.
 *
 * @note the working length cannot be smaller than the user buffer length
 *
 * @param[out] pUserBuffer     Pointer on the user buffer
 * @param[in] userLen          length of the user buffer
 * @param[in] pWorkingBuffer   Pointer on the working buffer
 * @param[in] workingLen       working buffer length
 * @param[in] copyBuf          if set _TRUE the data in the workingBuffer
 *                             will be copied to the userBuffer before the
 *                             workingBuffer is freed.
 *
 * @return the status of the operation
 *
 * @see icp_LacBufferResize()
 *
 ******************************************************************************/
CpaStatus icp_LacBufferRestore(Cpa8U *pUserBuffer,
			       Cpa32U userLen,
			       Cpa8U *pWorkingBuffer,
			       Cpa32U workingLen,
			       CpaBoolean copyBuf);

/**
*******************************************************************************
 * @ingroup LacMem
 *    Uses an instance specific user supplied virt2phys function to convert a
 *    virtual address to a physical address.
 *
 * @description
 *    Uses an instance specific user supplied virt2phys function to convert a
 *    virtual address to a physical address. A client of QA API can set the
 *    virt2phys function for an instance by using the
 *    cpaXxSetAddressTranslation() function. If the client does not set the
 *    virt2phys function and the instance is in kernel space then OS specific
 *    virt2phys function will be used. In user space the virt2phys function
 *    MUST be set by the user.
 *
 * @param[in] pVirtAddr         the virtual addr to be converted
 * @param[in] pServiceGen       Pointer on the sal_service_t structure
 *                              so client supplied virt2phys function can be
 *                              called.
 *
 * @return the physical address
 *
 ******************************************************************************/
CpaPhysicalAddr SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen);

#endif /* LAC_MEM_H */