summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2018-01-22 19:30:53 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2018-05-07 07:41:26 -0400
commit6e739d924fe9b778fa82396e0e941143f498acb8 (patch)
treef112ede8573c2f8bf76e0bdaadf33c6c71343820 /drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c
parente6b3bb4e6b3d4013f83ba6d31c780947f16cf410 (diff)
gpu: nvgpu: Userspace POSIX support
Add support for compiling nvgpu in a POSIX compliant userspace. This code adds all of the necessary abstraction interfaces (mostly stubbed) to enabled extremely limited and basic functionality in nvgpu. The goal of this code is to facilitate unit testing of the nvgpu common core. By doing this in userspace it is much easier to write tests that rely on very particular states within nvgpu since a user can very precisely control the state of nvgpu. JIRA NVGPU-525 Change-Id: I30e95016df14997d951075777e0585f912dc5960 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1683914 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c')
-rw-r--r--drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c b/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c
new file mode 100644
index 00000000..f8feb6a2
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c
@@ -0,0 +1,209 @@
1/*
2 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/bug.h>
24#include <nvgpu/dma.h>
25#include <nvgpu/gmmu.h>
26#include <nvgpu/kmem.h>
27#include <nvgpu/nvgpu_mem.h>
28
29/*
30 * DMA memory buffers - obviously we don't really have DMA in userspace but we
31 * can emulate a lot of the DMA mem functionality for unit testing purposes.
32 */
33
34int nvgpu_mem_begin(struct gk20a *g, struct nvgpu_mem *mem)
35{
36 return 0;
37}
38
39void nvgpu_mem_end(struct gk20a *g, struct nvgpu_mem *mem)
40{
41 return;
42}
43
44u32 nvgpu_mem_rd32(struct gk20a *g, struct nvgpu_mem *mem, u32 w)
45{
46 u32 *mem_ptr = (u32 *)mem->cpu_va;
47
48 return mem_ptr[w];
49}
50
51u32 nvgpu_mem_rd(struct gk20a *g, struct nvgpu_mem *mem, u32 offset)
52{
53 if (offset & 0x3)
54 BUG();
55
56 return nvgpu_mem_rd32(g, mem, offset >> 2);
57}
58
59void nvgpu_mem_rd_n(struct gk20a *g, struct nvgpu_mem *mem, u32 offset,
60 void *dest, u32 size)
61{
62 if (offset & 0x3 || size & 0x3)
63 BUG();
64
65 memcpy(dest, ((char *)mem->cpu_va) + offset, size);
66}
67
68void nvgpu_mem_wr32(struct gk20a *g, struct nvgpu_mem *mem, u32 w, u32 data)
69{
70 u32 *mem_ptr = (u32 *)mem->cpu_va;
71
72 mem_ptr[w] = data;
73}
74
75void nvgpu_mem_wr(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, u32 data)
76{
77 if (offset & 0x3)
78 BUG();
79
80 nvgpu_mem_wr32(g, mem, offset >> 2, data);
81}
82
83void nvgpu_mem_wr_n(struct gk20a *g, struct nvgpu_mem *mem, u32 offset,
84 void *src, u32 size)
85{
86 if (offset & 0x3 || size & 0x3)
87 BUG();
88
89 memcpy(((char *)mem->cpu_va) + offset, src, size);
90}
91
92void nvgpu_memset(struct gk20a *g, struct nvgpu_mem *mem, u32 offset,
93 u32 c, u32 size)
94{
95 memset(((char *)mem->cpu_va) + offset, c, size);
96}
97
98/*
99 * These functions are somewhat meaningless.
100 */
101u64 nvgpu_mem_get_addr(struct gk20a *g, struct nvgpu_mem *mem)
102{
103 return (u64)(uintptr_t)mem->cpu_va;
104}
105
106u64 nvgpu_mem_get_phys_addr(struct gk20a *g, struct nvgpu_mem *mem)
107{
108 return (u64)(uintptr_t)mem->cpu_va;
109}
110
111static struct nvgpu_sgl *nvgpu_mem_sgl_next(struct nvgpu_sgl *sgl)
112{
113 return NULL;
114}
115
116static u64 nvgpu_mem_sgl_phys(struct gk20a *g, struct nvgpu_sgl *sgl)
117{
118 struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl;
119
120 return (u64)(uintptr_t)mem->cpu_va;
121}
122
123static u64 nvgpu_mem_sgl_dma(struct nvgpu_sgl *sgl)
124{
125 struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl;
126
127 return (u64)(uintptr_t)mem->cpu_va;
128}
129
130static u64 nvgpu_mem_sgl_length(struct nvgpu_sgl *sgl)
131{
132 struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl;
133
134 return (u64)mem->aligned_size;
135}
136
137static u64 nvgpu_mem_sgl_gpu_addr(struct gk20a *g, struct nvgpu_sgl *sgl,
138 struct nvgpu_gmmu_attrs *attrs)
139{
140 struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl;
141
142 return mem->gpu_va;
143}
144
145static bool nvgpu_mem_sgt_iommuable(struct gk20a *g, struct nvgpu_sgt *sgt)
146{
147 return nvgpu_iommuable(g);
148}
149
150static void nvgpu_mem_sgt_free(struct gk20a *g, struct nvgpu_sgt *sgt)
151{
152 nvgpu_kfree(g, sgt);
153}
154
155static struct nvgpu_sgt_ops nvgpu_sgt_posix_ops = {
156 .sgl_next = nvgpu_mem_sgl_next,
157 .sgl_phys = nvgpu_mem_sgl_phys,
158 .sgl_dma = nvgpu_mem_sgl_dma,
159 .sgl_length = nvgpu_mem_sgl_length,
160 .sgl_gpu_addr = nvgpu_mem_sgl_gpu_addr,
161 .sgt_iommuable = nvgpu_mem_sgt_iommuable,
162 .sgt_free = nvgpu_mem_sgt_free,
163};
164
165struct nvgpu_sgt *nvgpu_sgt_create_from_mem(struct gk20a *g,
166 struct nvgpu_mem *mem)
167{
168 struct nvgpu_sgt *sgt = nvgpu_kzalloc(g, sizeof(*sgt));
169
170 if (sgt == NULL)
171 return NULL;
172
173 /*
174 * The userspace implementation is simple: a single 'entry' (which we
175 * only need the mem struct to describe). Maybe this could be expanded
176 * to be more interesting some day.
177 */
178 sgt->sgl = (struct nvgpu_sgl *)mem;
179 sgt->ops = &nvgpu_sgt_posix_ops;
180
181 return sgt;
182}
183
184int nvgpu_mem_create_from_mem(struct gk20a *g,
185 struct nvgpu_mem *dest, struct nvgpu_mem *src,
186 int start_page, int nr_pages)
187{
188 u64 start = start_page * PAGE_SIZE;
189 u64 size = nr_pages * PAGE_SIZE;
190
191 if (src->aperture != APERTURE_SYSMEM)
192 return -EINVAL;
193
194 /* Some silly things a caller might do... */
195 if (size > src->size)
196 return -EINVAL;
197 if ((start + size) > src->size)
198 return -EINVAL;
199
200 memset(dest, 0, sizeof(*dest));
201
202 dest->cpu_va = ((char *)src->cpu_va) + start;
203 dest->mem_flags = src->mem_flags | NVGPU_MEM_FLAG_SHADOW_COPY;
204 dest->aperture = src->aperture;
205 dest->skip_wmb = src->skip_wmb;
206 dest->size = size;
207
208 return 0;
209}