1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2014-2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 /**
24 * @file
25 * @brief MEMORY module implementation for Unix kernelmode
26 *
27 * This implementation uses the NVIDIA OS interface into the unix kernels.
28 */
29
30 #if !PORT_IS_KERNEL_BUILD
31 #error "This file can only be compiled as part of the kernel build."
32 #endif
33 #if !NVOS_IS_UNIX
34 #error "This file can only be compiled on Unix."
35 #endif
36
37 #include "nvport/nvport.h"
38 #include "os-interface.h"
39
40 /**
41 * @note All kernel memory in unix is non-paged.
42 */
43 void *
_portMemAllocPagedUntracked(NvLength lengthBytes)44 _portMemAllocPagedUntracked
45 (
46 NvLength lengthBytes
47 )
48 {
49 return _portMemAllocNonPagedUntracked(lengthBytes);
50 }
51
52 void *
_portMemAllocNonPagedUntracked(NvLength lengthBytes)53 _portMemAllocNonPagedUntracked
54 (
55 NvLength lengthBytes
56 )
57 {
58 void *pMem = NULL;
59 PORT_ASSERT_CHECKED(lengthBytes > 0);
60 if (lengthBytes > 0)
61 os_alloc_mem(&pMem, lengthBytes);
62 return pMem;
63 }
64
65
66
67 void
_portMemFreeUntracked(void * pData)68 _portMemFreeUntracked
69 (
70 void *pData
71 )
72 {
73 if (pData != NULL)
74 {
75 os_free_mem(pData);
76 }
77 }
78
79 void *
portMemCopy(void * pDestination,NvLength destSize,const void * pSource,NvLength srcSize)80 portMemCopy
81 (
82 void *pDestination,
83 NvLength destSize,
84 const void *pSource,
85 NvLength srcSize
86 )
87 {
88 // API guarantees this is a NOP when destSize==0
89 if (destSize == 0)
90 {
91 return pDestination;
92 }
93
94 PORT_ASSERT_CHECKED(pDestination != NULL);
95 PORT_ASSERT_CHECKED(pSource != NULL);
96 PORT_ASSERT_CHECKED(srcSize <= destSize);
97 PORT_ASSERT_CHECKED(!portUtilCheckOverlap(pDestination, destSize,
98 pSource, srcSize));
99
100 if ((pSource == NULL) || (pDestination == NULL) || (srcSize > destSize))
101 {
102 return NULL;
103 }
104 return os_mem_copy(pDestination, pSource, srcSize);
105 }
106
107
108 void *
portMemSet(void * pData,NvU8 value,NvLength lengthBytes)109 portMemSet
110 (
111 void *pData,
112 NvU8 value,
113 NvLength lengthBytes
114 )
115 {
116 if (lengthBytes == 0)
117 {
118 return pData;
119 }
120 if (pData == NULL)
121 {
122 return pData;
123 }
124 return os_mem_set(pData, value, lengthBytes);
125 }
126
127 NvS32
portMemCmp(const void * pData0,const void * pData1,NvLength lengthBytes)128 portMemCmp
129 (
130 const void *pData0,
131 const void *pData1,
132 NvLength lengthBytes
133 )
134 {
135 if (lengthBytes == 0)
136 {
137 return 0;
138 }
139 if ((pData0 == NULL) || (pData1 == NULL))
140 {
141 return -1;
142 }
143 return os_mem_cmp(pData0, pData1, lengthBytes);
144 }
145
146
147
148 #define PORT_MEM_USE_GENERIC_portMemSetPattern
149 #define PORT_MEM_USE_GENERIC_portMemMove
150 #include "memory_generic.h"
151
152 NV_STATUS
portMemExCopyFromUser(const NvP64 pUser,void * pKernel,NvLength lengthBytes)153 portMemExCopyFromUser
154 (
155 const NvP64 pUser,
156 void *pKernel,
157 NvLength lengthBytes
158 )
159 {
160 if (pKernel == NULL)
161 {
162 return NV_ERR_INVALID_POINTER;
163 }
164 if (lengthBytes == 0)
165 {
166 return NV_ERR_INVALID_ARGUMENT;
167 }
168 return os_memcpy_from_user(pKernel, NvP64_VALUE(pUser), lengthBytes);
169 }
170
171 NV_STATUS
portMemExCopyToUser(const void * pKernel,NvP64 pUser,NvLength lengthBytes)172 portMemExCopyToUser
173 (
174 const void *pKernel,
175 NvP64 pUser,
176 NvLength lengthBytes
177 )
178 {
179 if (pKernel == NULL)
180 {
181 return NV_ERR_INVALID_POINTER;
182 }
183 if (lengthBytes == 0)
184 {
185 return NV_ERR_INVALID_ARGUMENT;
186 }
187 return os_memcpy_to_user(NvP64_VALUE(pUser), (void*)pKernel, lengthBytes);
188 }
189
190 NvLength
portMemExGetPageSize(void)191 portMemExGetPageSize(void)
192 {
193 return os_page_size;
194 }
195
196 // Large allocations (>KMALLOC_LIMIT) will fail, but it is safe to call
197 NvBool
portMemExSafeForPagedAlloc(void)198 portMemExSafeForPagedAlloc(void)
199 {
200 return NV_TRUE;
201 }
202 NvBool
portMemExSafeForNonPagedAlloc(void)203 portMemExSafeForNonPagedAlloc(void)
204 {
205 return NV_TRUE;
206 }
207