Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/gfx_private/gfxp_vm.c
+++ new/usr/src/uts/i86pc/io/gfx_private/gfxp_vm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + *
26 + * Copyright 2018 Joyent, Inc.
25 27 */
26 28
27 29 #include <sys/debug.h>
28 30 #include <sys/types.h>
29 31 #include <sys/param.h>
30 32 #include <sys/time.h>
31 33 #include <sys/buf.h>
32 34 #include <sys/errno.h>
33 35 #include <sys/systm.h>
34 36 #include <sys/conf.h>
35 37 #include <sys/signal.h>
36 38 #include <sys/file.h>
37 39 #include <sys/uio.h>
38 40 #include <sys/ioctl.h>
39 41 #include <sys/map.h>
40 42 #include <sys/proc.h>
41 43 #include <sys/user.h>
42 44 #include <sys/mman.h>
43 45 #include <sys/cred.h>
44 46 #include <sys/open.h>
45 47 #include <sys/stat.h>
46 48 #include <sys/utsname.h>
47 49 #include <sys/kmem.h>
48 50 #include <sys/cmn_err.h>
49 51 #include <sys/vnode.h>
50 52 #include <vm/page.h>
51 53 #include <vm/as.h>
52 54 #include <vm/hat.h>
53 55 #include <vm/seg.h>
54 56 #include <vm/seg_kmem.h>
55 57 #include <vm/hat_i86.h>
56 58 #include <sys/vmsystm.h>
57 59 #include <sys/ddi.h>
58 60 #include <sys/devops.h>
59 61 #include <sys/sunddi.h>
60 62 #include <sys/ddi_impldefs.h>
61 63 #include <sys/fs/snode.h>
62 64 #include <sys/pci.h>
63 65 #include <sys/modctl.h>
64 66 #include <sys/uio.h>
65 67 #include <sys/visual_io.h>
66 68 #include <sys/fbio.h>
67 69 #include <sys/ddidmareq.h>
68 70 #include <sys/tnf_probe.h>
69 71 #include <sys/kstat.h>
70 72 #include <sys/callb.h>
71 73 #include <sys/promif.h>
72 74 #include <sys/atomic.h>
73 75 #include <sys/gfx_private.h>
74 76
75 77 #ifdef __xpv
76 78 #include <sys/hypervisor.h>
77 79 #endif
78 80
79 81 /*
80 82 * Create a kva mapping for a pa (start..start+size) with
81 83 * the specified cache attributes (mode).
82 84 */
83 85 gfxp_kva_t
84 86 gfxp_map_kernel_space(uint64_t start, size_t size, uint32_t mode)
85 87 {
86 88 uint_t pgoffset;
87 89 uint64_t base;
88 90 pgcnt_t npages;
89 91 caddr_t cvaddr;
90 92 int hat_flags;
91 93 uint_t hat_attr;
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
92 94 pfn_t pfn;
93 95
94 96 if (size == 0)
95 97 return (0);
96 98
97 99 #ifdef __xpv
98 100 /*
99 101 * The hypervisor doesn't allow r/w mappings to some pages, such as
100 102 * page tables, gdt, etc. Detect %cr3 to notify users of this interface.
101 103 */
102 - if (start == mmu_ptob(mmu_btop(getcr3())))
104 + if (start == mmu_ptob(mmu_btop(getcr3_pa())))
103 105 return (0);
104 106 #endif
105 107
106 108 if (mode == GFXP_MEMORY_CACHED)
107 109 hat_attr = HAT_STORECACHING_OK;
108 110 else if (mode == GFXP_MEMORY_WRITECOMBINED)
109 111 hat_attr = HAT_MERGING_OK | HAT_PLAT_NOCACHE;
110 112 else /* GFXP_MEMORY_UNCACHED */
111 113 hat_attr = HAT_STRICTORDER | HAT_PLAT_NOCACHE;
112 114 hat_flags = HAT_LOAD_LOCK;
113 115 pgoffset = start & PAGEOFFSET;
114 116 base = start - pgoffset;
115 117 npages = btopr(size + pgoffset);
116 118 cvaddr = vmem_alloc(heap_arena, ptob(npages), VM_NOSLEEP);
117 119 if (cvaddr == NULL)
118 120 return (NULL);
119 121
120 122 #ifdef __xpv
121 123 ASSERT(DOMAIN_IS_INITDOMAIN(xen_info));
122 124 pfn = xen_assign_pfn(mmu_btop(base));
123 125 #else
124 126 pfn = btop(base);
125 127 #endif
126 128
127 129 hat_devload(kas.a_hat, cvaddr, ptob(npages), pfn,
128 130 PROT_READ|PROT_WRITE|hat_attr, hat_flags);
129 131 return (cvaddr + pgoffset);
130 132 }
131 133
132 134 /*
133 135 * Destroy the mapping created by gfxp_map_kernel_space().
134 136 * Physical memory is not reclaimed.
135 137 */
136 138 void
137 139 gfxp_unmap_kernel_space(gfxp_kva_t address, size_t size)
138 140 {
139 141 uint_t pgoffset;
140 142 caddr_t base;
141 143 pgcnt_t npages;
142 144
143 145 if (size == 0 || address == NULL)
144 146 return;
145 147
146 148 pgoffset = (uintptr_t)address & PAGEOFFSET;
147 149 base = (caddr_t)address - pgoffset;
148 150 npages = btopr(size + pgoffset);
149 151 hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
150 152 vmem_free(heap_arena, base, ptob(npages));
151 153 }
152 154
153 155 /*
154 156 * For a VA return the pfn
155 157 */
156 158 int
157 159 gfxp_va2pa(struct as *as, caddr_t addr, uint64_t *pa)
158 160 {
159 161 #ifdef __xpv
160 162 ASSERT(DOMAIN_IS_INITDOMAIN(xen_info));
161 163 *pa = pa_to_ma(pfn_to_pa(hat_getpfnum(as->a_hat, addr)));
162 164 #else
163 165 *pa = pfn_to_pa(hat_getpfnum(as->a_hat, addr));
164 166 #endif
165 167 return (0);
166 168 }
167 169
168 170 /*
169 171 * NOP now
170 172 */
171 173 /* ARGSUSED */
172 174 void
173 175 gfxp_fix_mem_cache_attrs(caddr_t kva_start, size_t length, int cache_attr)
174 176 {
175 177 }
176 178
177 179 int
178 180 gfxp_ddi_dma_mem_alloc(ddi_dma_handle_t handle, size_t length,
179 181 ddi_device_acc_attr_t *accattrp, uint_t flags, int (*waitfp) (caddr_t),
180 182 caddr_t arg, caddr_t *kaddrp, size_t *real_length,
181 183 ddi_acc_handle_t *handlep)
182 184 {
183 185 uint_t l_flags = flags & ~IOMEM_DATA_MASK; /* clear cache attrs */
184 186 int e;
185 187
186 188 /*
187 189 * Set an appropriate attribute from devacc_attr_dataorder
188 190 * to keep compatibility. The cache attributes are igonred
189 191 * if specified.
190 192 */
191 193 if (accattrp != NULL) {
192 194 if (accattrp->devacc_attr_dataorder == DDI_STRICTORDER_ACC) {
193 195 l_flags |= IOMEM_DATA_UNCACHED;
194 196 } else if (accattrp->devacc_attr_dataorder ==
195 197 DDI_MERGING_OK_ACC) {
196 198 l_flags |= IOMEM_DATA_UC_WR_COMBINE;
197 199 } else {
198 200 l_flags |= IOMEM_DATA_CACHED;
199 201 }
200 202 }
201 203
202 204 e = ddi_dma_mem_alloc(handle, length, accattrp, l_flags, waitfp,
203 205 arg, kaddrp, real_length, handlep);
204 206 return (e);
205 207 }
206 208
207 209 int
208 210 gfxp_mlock_user_memory(caddr_t address, size_t length)
209 211 {
210 212 struct as *as = ttoproc(curthread)->p_as;
211 213 int error = 0;
212 214
213 215 if (((uintptr_t)address & PAGEOFFSET) != 0 || length == 0)
214 216 return (set_errno(EINVAL));
215 217
216 218 if (valid_usr_range(address, length, 0, as, as->a_userlimit) !=
217 219 RANGE_OKAY)
218 220 return (set_errno(ENOMEM));
219 221
220 222 error = as_ctl(as, address, length, MC_LOCK, 0, 0, NULL, 0);
221 223 if (error)
222 224 (void) set_errno(error);
223 225
224 226 return (error);
225 227 }
226 228
227 229 int
228 230 gfxp_munlock_user_memory(caddr_t address, size_t length)
229 231 {
230 232 struct as *as = ttoproc(curthread)->p_as;
231 233 int error = 0;
232 234
233 235 if (((uintptr_t)address & PAGEOFFSET) != 0 || length == 0)
234 236 return (set_errno(EINVAL));
235 237
236 238 if (valid_usr_range(address, length, 0, as, as->a_userlimit) !=
237 239 RANGE_OKAY)
238 240 return (set_errno(ENOMEM));
239 241
240 242 error = as_ctl(as, address, length, MC_UNLOCK, 0, 0, NULL, 0);
241 243 if (error)
242 244 (void) set_errno(error);
243 245
244 246 return (error);
245 247 }
246 248
247 249 gfx_maddr_t
248 250 gfxp_convert_addr(paddr_t paddr)
249 251 {
250 252 #ifdef __xpv
251 253 ASSERT(DOMAIN_IS_INITDOMAIN(xen_info));
252 254 return (pfn_to_pa(xen_assign_pfn(btop(paddr))));
253 255 #else
254 256 return ((gfx_maddr_t)paddr);
255 257 #endif
256 258 }
257 259
258 260 /*
259 261 * Support getting VA space separately from pages
260 262 */
261 263
262 264 /*
263 265 * A little like gfxp_map_kernel_space, but
264 266 * just the vmem_alloc part.
265 267 */
266 268 caddr_t
267 269 gfxp_alloc_kernel_space(size_t size)
268 270 {
269 271 caddr_t cvaddr;
270 272 pgcnt_t npages;
271 273
272 274 npages = btopr(size);
273 275 cvaddr = vmem_alloc(heap_arena, ptob(npages), VM_NOSLEEP);
274 276 return (cvaddr);
275 277 }
276 278
277 279 /*
278 280 * Like gfxp_unmap_kernel_space, but
279 281 * just the vmem_free part.
280 282 */
281 283 void
282 284 gfxp_free_kernel_space(caddr_t address, size_t size)
283 285 {
284 286
285 287 uint_t pgoffset;
286 288 caddr_t base;
287 289 pgcnt_t npages;
288 290
289 291 if (size == 0 || address == NULL)
290 292 return;
291 293
292 294 pgoffset = (uintptr_t)address & PAGEOFFSET;
293 295 base = (caddr_t)address - pgoffset;
294 296 npages = btopr(size + pgoffset);
295 297 vmem_free(heap_arena, base, ptob(npages));
296 298 }
297 299
298 300 /*
299 301 * Like gfxp_map_kernel_space, but
300 302 * just the hat_devload part.
301 303 */
302 304 void
303 305 gfxp_load_kernel_space(uint64_t start, size_t size,
304 306 uint32_t mode, caddr_t cvaddr)
305 307 {
306 308 uint_t pgoffset;
307 309 uint64_t base;
308 310 pgcnt_t npages;
309 311 int hat_flags;
310 312 uint_t hat_attr;
↓ open down ↓ |
198 lines elided |
↑ open up ↑ |
311 313 pfn_t pfn;
312 314
313 315 if (size == 0)
314 316 return;
315 317
316 318 #ifdef __xpv
317 319 /*
318 320 * The hypervisor doesn't allow r/w mappings to some pages, such as
319 321 * page tables, gdt, etc. Detect %cr3 to notify users of this interface.
320 322 */
321 - if (start == mmu_ptob(mmu_btop(getcr3())))
323 + if (start == mmu_ptob(mmu_btop(getcr3_pa())))
322 324 return;
323 325 #endif
324 326
325 327 if (mode == GFXP_MEMORY_CACHED)
326 328 hat_attr = HAT_STORECACHING_OK;
327 329 else if (mode == GFXP_MEMORY_WRITECOMBINED)
328 330 hat_attr = HAT_MERGING_OK | HAT_PLAT_NOCACHE;
329 331 else /* GFXP_MEMORY_UNCACHED */
330 332 hat_attr = HAT_STRICTORDER | HAT_PLAT_NOCACHE;
331 333 hat_flags = HAT_LOAD_LOCK;
332 334
333 335 pgoffset = start & PAGEOFFSET;
334 336 base = start - pgoffset;
335 337 npages = btopr(size + pgoffset);
336 338
337 339 #ifdef __xpv
338 340 ASSERT(DOMAIN_IS_INITDOMAIN(xen_info));
339 341 pfn = xen_assign_pfn(mmu_btop(base));
340 342 #else
341 343 pfn = btop(base);
342 344 #endif
343 345
344 346 hat_devload(kas.a_hat, cvaddr, ptob(npages), pfn,
345 347 PROT_READ|PROT_WRITE|hat_attr, hat_flags);
346 348 }
347 349
348 350 /*
349 351 * Like gfxp_unmap_kernel_space, but
350 352 * just the had_unload part.
351 353 */
352 354 void
353 355 gfxp_unload_kernel_space(caddr_t address, size_t size)
354 356 {
355 357 uint_t pgoffset;
356 358 caddr_t base;
357 359 pgcnt_t npages;
358 360
359 361 if (size == 0 || address == NULL)
360 362 return;
361 363
362 364 pgoffset = (uintptr_t)address & PAGEOFFSET;
363 365 base = (caddr_t)address - pgoffset;
364 366 npages = btopr(size + pgoffset);
365 367 hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
366 368 }
367 369
368 370 /*
369 371 * Note that "mempool" is optional and normally disabled in drm_gem.c
370 372 * (see HAS_MEM_POOL). Let's just stub these out so we can reduce
371 373 * changes from the upstream in the DRM driver code.
372 374 */
373 375
374 376 void
375 377 gfxp_mempool_init(void)
376 378 {
377 379 }
378 380
379 381 void
380 382 gfxp_mempool_destroy(void)
381 383 {
382 384 }
383 385
384 386 /* ARGSUSED */
385 387 int
386 388 gfxp_alloc_from_mempool(struct gfxp_pmem_cookie *cookie, caddr_t *kva,
387 389 pfn_t *pgarray, pgcnt_t alen, int flags)
388 390 {
389 391 return (-1);
390 392 }
391 393
392 394 /* ARGSUSED */
393 395 void
394 396 gfxp_free_mempool(struct gfxp_pmem_cookie *cookie, caddr_t kva, size_t len)
395 397 {
396 398 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX