1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "qat_utils.h"
5 
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sys/systm.h>
9 #include <sys/kernel.h>
10 #include <sys/malloc.h>
11 #include <sys/proc.h>
12 #include <sys/sched.h>
13 #include <sys/time.h>
14 #include <machine/stdarg.h>
15 #include <vm/vm.h>
16 #include <vm/pmap.h>
17 
18 /**
19  *
20  * @brief Private data structure
21  *
22  *  Data struct to store the information on the
23  *  memory allocated. This structure is stored at the beginning of
24  *  the allocated chunck of memory
25  *  size is the no of byte passed to the memory allocation functions
26  *  mSize is the real size of the memory required to the OS
27  *
28  *  +----------------------------+--------------------------------+
29  *  | QatUtilsMemAllocInfoStruct | memory returned to user (size) |
30  *  +----------------------------+--------------------------------+
31  *  ^                            ^
32  *  mAllocMemPtr                 Ptr returned to the caller of MemAlloc*
33  *
34  */
35 
36 typedef struct _QatUtilsMemAllocInfoStruct {
37 	void *mAllocMemPtr; /* memory addr returned by the kernel */
38 	uint32_t mSize;     /* allocated size */
39 } QatUtilsMemAllocInfoStruct;
40 
41 /**************************************
42  * Memory functions
43  *************************************/
44 void *
45 qatUtilsMemAllocContiguousNUMA(uint32_t size, uint32_t node, uint32_t alignment)
46 {
47 	void *ptr = NULL;
48 	void *pRet = NULL;
49 	uint32_t alignment_offset = 0;
50 
51 	QatUtilsMemAllocInfoStruct memInfo = { 0 };
52 	if (size == 0 || alignment < 1) {
53 		QAT_UTILS_LOG(
54 		    "QatUtilsMemAllocNUMA: size or alignment are zero.\n");
55 		return NULL;
56 	}
57 	if (alignment & (alignment - 1)) {
58 		QAT_UTILS_LOG(
59 		    "QatUtilsMemAllocNUMA: Expecting alignment of a power.\n");
60 		return NULL;
61 	}
62 
63 	memInfo.mSize = size + alignment + sizeof(QatUtilsMemAllocInfoStruct);
64 	ptr = contigmalloc(memInfo.mSize, M_QAT, M_WAITOK, 0, ~1UL, 64, 0);
65 
66 	memInfo.mAllocMemPtr = ptr;
67 	pRet =
68 	    (char *)memInfo.mAllocMemPtr + sizeof(QatUtilsMemAllocInfoStruct);
69 #ifdef __x86_64__
70 	alignment_offset = (uint64_t)pRet % alignment;
71 #else
72 	alignment_offset = (uint32_t)pRet % alignment;
73 #endif
74 	pRet = (char *)pRet + (alignment - alignment_offset);
75 	memcpy(((char *)pRet) - sizeof(QatUtilsMemAllocInfoStruct),
76 	       &memInfo,
77 	       sizeof(QatUtilsMemAllocInfoStruct));
78 
79 	return pRet;
80 }
81 
82 void
83 qatUtilsMemFreeNUMA(void *ptr)
84 {
85 	QatUtilsMemAllocInfoStruct *memInfo = NULL;
86 
87 	memInfo =
88 	    (QatUtilsMemAllocInfoStruct *)((int8_t *)ptr -
89 					   sizeof(QatUtilsMemAllocInfoStruct));
90 	if (memInfo->mSize == 0 || memInfo->mAllocMemPtr == NULL) {
91 		QAT_UTILS_LOG(
92 		    "QatUtilsMemAlignedFree: Detected corrupted data: memory leak!\n");
93 		return;
94 	}
95 	contigfree(memInfo->mAllocMemPtr, memInfo->mSize, M_QAT);
96 }
97 
98 CpaStatus
99 qatUtilsSleep(uint32_t milliseconds)
100 {
101 	if (milliseconds != 0) {
102 		pause("qatUtils sleep", milliseconds * hz / (1000));
103 	} else {
104 		sched_relinquish(curthread);
105 	}
106 	return CPA_STATUS_SUCCESS;
107 }
108 
109 void
110 qatUtilsYield(void)
111 {
112 	sched_relinquish(curthread);
113 }
114