4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright 2018 Joyent, Inc.
29 #include <sys/debug.h>
30 #include <sys/types.h>
31 #include <sys/param.h>
34 #include <sys/errno.h>
35 #include <sys/systm.h>
37 #include <sys/signal.h>
40 #include <sys/ioctl.h>
48 #include <sys/utsname.h>
50 #include <sys/cmn_err.h>
51 #include <sys/vnode.h>
56 #include <vm/seg_kmem.h>
57 #include <vm/hat_i86.h>
58 #include <sys/vmsystm.h>
60 #include <sys/devops.h>
61 #include <sys/sunddi.h>
62 #include <sys/ddi_impldefs.h>
63 #include <sys/fs/snode.h>
65 #include <sys/modctl.h>
67 #include <sys/visual_io.h>
69 #include <sys/ddidmareq.h>
70 #include <sys/tnf_probe.h>
71 #include <sys/kstat.h>
72 #include <sys/callb.h>
73 #include <sys/promif.h>
74 #include <sys/atomic.h>
75 #include <sys/gfx_private.h>
79 * Create a kva mapping for a pa (start..start+size) with
80 * the specified cache attributes (mode).
83 gfxp_map_kernel_space(uint64_t start
, size_t size
, uint32_t mode
)
96 if (mode
== GFXP_MEMORY_CACHED
)
97 hat_attr
= HAT_STORECACHING_OK
;
98 else if (mode
== GFXP_MEMORY_WRITECOMBINED
)
99 hat_attr
= HAT_MERGING_OK
| HAT_PLAT_NOCACHE
;
100 else /* GFXP_MEMORY_UNCACHED */
101 hat_attr
= HAT_STRICTORDER
| HAT_PLAT_NOCACHE
;
102 hat_flags
= HAT_LOAD_LOCK
;
103 pgoffset
= start
& PAGEOFFSET
;
104 base
= start
- pgoffset
;
105 npages
= btopr(size
+ pgoffset
);
106 cvaddr
= vmem_alloc(heap_arena
, ptob(npages
), VM_NOSLEEP
);
112 hat_devload(kas
.a_hat
, cvaddr
, ptob(npages
), pfn
,
113 PROT_READ
|PROT_WRITE
|hat_attr
, hat_flags
);
114 return (cvaddr
+ pgoffset
);
118 * Destroy the mapping created by gfxp_map_kernel_space().
119 * Physical memory is not reclaimed.
122 gfxp_unmap_kernel_space(gfxp_kva_t address
, size_t size
)
128 if (size
== 0 || address
== NULL
)
131 pgoffset
= (uintptr_t)address
& PAGEOFFSET
;
132 base
= (caddr_t
)address
- pgoffset
;
133 npages
= btopr(size
+ pgoffset
);
134 hat_unload(kas
.a_hat
, base
, ptob(npages
), HAT_UNLOAD_UNLOCK
);
135 vmem_free(heap_arena
, base
, ptob(npages
));
139 * For a VA return the pfn
142 gfxp_va2pa(struct as
*as
, caddr_t addr
, uint64_t *pa
)
144 *pa
= pfn_to_pa(hat_getpfnum(as
->a_hat
, addr
));
153 gfxp_fix_mem_cache_attrs(caddr_t kva_start
, size_t length
, int cache_attr
)
158 gfxp_ddi_dma_mem_alloc(ddi_dma_handle_t handle
, size_t length
,
159 ddi_device_acc_attr_t
*accattrp
, uint_t flags
, int (*waitfp
) (caddr_t
),
160 caddr_t arg
, caddr_t
*kaddrp
, size_t *real_length
,
161 ddi_acc_handle_t
*handlep
)
163 uint_t l_flags
= flags
& ~IOMEM_DATA_MASK
; /* clear cache attrs */
167 * Set an appropriate attribute from devacc_attr_dataorder
168 * to keep compatibility. The cache attributes are igonred
171 if (accattrp
!= NULL
) {
172 if (accattrp
->devacc_attr_dataorder
== DDI_STRICTORDER_ACC
) {
173 l_flags
|= IOMEM_DATA_UNCACHED
;
174 } else if (accattrp
->devacc_attr_dataorder
==
175 DDI_MERGING_OK_ACC
) {
176 l_flags
|= IOMEM_DATA_UC_WR_COMBINE
;
178 l_flags
|= IOMEM_DATA_CACHED
;
182 e
= ddi_dma_mem_alloc(handle
, length
, accattrp
, l_flags
, waitfp
,
183 arg
, kaddrp
, real_length
, handlep
);
188 gfxp_mlock_user_memory(caddr_t address
, size_t length
)
190 struct as
*as
= ttoproc(curthread
)->p_as
;
193 if (((uintptr_t)address
& PAGEOFFSET
) != 0 || length
== 0)
194 return (set_errno(EINVAL
));
196 if (valid_usr_range(address
, length
, 0, as
, as
->a_userlimit
) !=
198 return (set_errno(ENOMEM
));
200 error
= as_ctl(as
, address
, length
, MC_LOCK
, 0, 0, NULL
, 0);
202 (void) set_errno(error
);
208 gfxp_munlock_user_memory(caddr_t address
, size_t length
)
210 struct as
*as
= ttoproc(curthread
)->p_as
;
213 if (((uintptr_t)address
& PAGEOFFSET
) != 0 || length
== 0)
214 return (set_errno(EINVAL
));
216 if (valid_usr_range(address
, length
, 0, as
, as
->a_userlimit
) !=
218 return (set_errno(ENOMEM
));
220 error
= as_ctl(as
, address
, length
, MC_UNLOCK
, 0, 0, NULL
, 0);
222 (void) set_errno(error
);
228 gfxp_convert_addr(paddr_t paddr
)
230 return ((gfx_maddr_t
)paddr
);
234 * Support getting VA space separately from pages
238 * A little like gfxp_map_kernel_space, but
239 * just the vmem_alloc part.
242 gfxp_alloc_kernel_space(size_t size
)
247 npages
= btopr(size
);
248 cvaddr
= vmem_alloc(heap_arena
, ptob(npages
), VM_NOSLEEP
);
253 * Like gfxp_unmap_kernel_space, but
254 * just the vmem_free part.
257 gfxp_free_kernel_space(caddr_t address
, size_t size
)
264 if (size
== 0 || address
== NULL
)
267 pgoffset
= (uintptr_t)address
& PAGEOFFSET
;
268 base
= (caddr_t
)address
- pgoffset
;
269 npages
= btopr(size
+ pgoffset
);
270 vmem_free(heap_arena
, base
, ptob(npages
));
274 * Like gfxp_map_kernel_space, but
275 * just the hat_devload part.
278 gfxp_load_kernel_space(uint64_t start
, size_t size
,
279 uint32_t mode
, caddr_t cvaddr
)
291 if (mode
== GFXP_MEMORY_CACHED
)
292 hat_attr
= HAT_STORECACHING_OK
;
293 else if (mode
== GFXP_MEMORY_WRITECOMBINED
)
294 hat_attr
= HAT_MERGING_OK
| HAT_PLAT_NOCACHE
;
295 else /* GFXP_MEMORY_UNCACHED */
296 hat_attr
= HAT_STRICTORDER
| HAT_PLAT_NOCACHE
;
297 hat_flags
= HAT_LOAD_LOCK
;
299 pgoffset
= start
& PAGEOFFSET
;
300 base
= start
- pgoffset
;
301 npages
= btopr(size
+ pgoffset
);
305 hat_devload(kas
.a_hat
, cvaddr
, ptob(npages
), pfn
,
306 PROT_READ
|PROT_WRITE
|hat_attr
, hat_flags
);
310 * Like gfxp_unmap_kernel_space, but
311 * just the had_unload part.
314 gfxp_unload_kernel_space(caddr_t address
, size_t size
)
320 if (size
== 0 || address
== NULL
)
323 pgoffset
= (uintptr_t)address
& PAGEOFFSET
;
324 base
= (caddr_t
)address
- pgoffset
;
325 npages
= btopr(size
+ pgoffset
);
326 hat_unload(kas
.a_hat
, base
, ptob(npages
), HAT_UNLOAD_UNLOCK
);
330 * Note that "mempool" is optional and normally disabled in drm_gem.c
331 * (see HAS_MEM_POOL). Let's just stub these out so we can reduce
332 * changes from the upstream in the DRM driver code.
336 gfxp_mempool_init(void)
341 gfxp_mempool_destroy(void)
347 gfxp_alloc_from_mempool(struct gfxp_pmem_cookie
*cookie
, caddr_t
*kva
,
348 pfn_t
*pgarray
, pgcnt_t alen
, int flags
)
355 gfxp_free_mempool(struct gfxp_pmem_cookie
*cookie
, caddr_t kva
, size_t len
)