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.
27 #include <sys/debug.h>
28 #include <sys/types.h>
29 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/systm.h>
35 #include <sys/signal.h>
38 #include <sys/ioctl.h>
46 #include <sys/utsname.h>
48 #include <sys/cmn_err.h>
49 #include <sys/vnode.h>
54 #include <vm/seg_kmem.h>
55 #include <vm/hat_i86.h>
56 #include <sys/vmsystm.h>
58 #include <sys/devops.h>
59 #include <sys/sunddi.h>
60 #include <sys/ddi_impldefs.h>
61 #include <sys/fs/snode.h>
63 #include <sys/modctl.h>
65 #include <sys/visual_io.h>
67 #include <sys/ddidmareq.h>
68 #include <sys/tnf_probe.h>
69 #include <sys/kstat.h>
70 #include <sys/callb.h>
71 #include <sys/promif.h>
72 #include <sys/atomic.h>
73 #include <sys/gfx_private.h>
77 * Create a kva mapping for a pa (start..start+size) with
78 * the specified cache attributes (mode).
81 gfxp_map_kernel_space(uint64_t start
, size_t size
, uint32_t mode
)
95 if (mode
== GFXP_MEMORY_CACHED
)
96 hat_attr
= HAT_STORECACHING_OK
;
97 else if (mode
== GFXP_MEMORY_WRITECOMBINED
)
98 hat_attr
= HAT_MERGING_OK
| HAT_PLAT_NOCACHE
;
99 else /* GFXP_MEMORY_UNCACHED */
100 hat_attr
= HAT_STRICTORDER
| HAT_PLAT_NOCACHE
;
101 hat_flags
= HAT_LOAD_LOCK
;
102 pgoffset
= start
& PAGEOFFSET
;
103 base
= start
- pgoffset
;
104 npages
= btopr(size
+ pgoffset
);
105 cvaddr
= vmem_alloc(heap_arena
, ptob(npages
), VM_NOSLEEP
);
111 hat_devload(kas
.a_hat
, cvaddr
, ptob(npages
), pfn
,
112 PROT_READ
|PROT_WRITE
|hat_attr
, hat_flags
);
113 return (cvaddr
+ pgoffset
);
117 * Destroy the mapping created by gfxp_map_kernel_space().
118 * Physical memory is not reclaimed.
121 gfxp_unmap_kernel_space(gfxp_kva_t address
, size_t size
)
127 if (size
== 0 || address
== NULL
)
130 pgoffset
= (uintptr_t)address
& PAGEOFFSET
;
131 base
= (caddr_t
)address
- pgoffset
;
132 npages
= btopr(size
+ pgoffset
);
133 hat_unload(kas
.a_hat
, base
, ptob(npages
), HAT_UNLOAD_UNLOCK
);
134 vmem_free(heap_arena
, base
, ptob(npages
));
138 * For a VA return the pfn
141 gfxp_va2pa(struct as
*as
, caddr_t addr
, uint64_t *pa
)
143 *pa
= pfn_to_pa(hat_getpfnum(as
->a_hat
, addr
));
152 gfxp_fix_mem_cache_attrs(caddr_t kva_start
, size_t length
, int cache_attr
)
157 gfxp_ddi_dma_mem_alloc(ddi_dma_handle_t handle
, size_t length
,
158 ddi_device_acc_attr_t
*accattrp
, uint_t flags
, int (*waitfp
) (caddr_t
),
159 caddr_t arg
, caddr_t
*kaddrp
, size_t *real_length
,
160 ddi_acc_handle_t
*handlep
)
162 uint_t l_flags
= flags
& ~IOMEM_DATA_MASK
; /* clear cache attrs */
166 * Set an appropriate attribute from devacc_attr_dataorder
167 * to keep compatibility. The cache attributes are igonred
170 if (accattrp
!= NULL
) {
171 if (accattrp
->devacc_attr_dataorder
== DDI_STRICTORDER_ACC
) {
172 l_flags
|= IOMEM_DATA_UNCACHED
;
173 } else if (accattrp
->devacc_attr_dataorder
==
174 DDI_MERGING_OK_ACC
) {
175 l_flags
|= IOMEM_DATA_UC_WR_COMBINE
;
177 l_flags
|= IOMEM_DATA_CACHED
;
181 e
= ddi_dma_mem_alloc(handle
, length
, accattrp
, l_flags
, waitfp
,
182 arg
, kaddrp
, real_length
, handlep
);
187 gfxp_mlock_user_memory(caddr_t address
, size_t length
)
189 struct as
*as
= ttoproc(curthread
)->p_as
;
192 if (((uintptr_t)address
& PAGEOFFSET
) != 0 || length
== 0)
193 return (set_errno(EINVAL
));
195 if (valid_usr_range(address
, length
, 0, as
, as
->a_userlimit
) !=
197 return (set_errno(ENOMEM
));
199 error
= as_ctl(as
, address
, length
, MC_LOCK
, 0, 0, NULL
, 0);
201 (void) set_errno(error
);
207 gfxp_munlock_user_memory(caddr_t address
, size_t length
)
209 struct as
*as
= ttoproc(curthread
)->p_as
;
212 if (((uintptr_t)address
& PAGEOFFSET
) != 0 || length
== 0)
213 return (set_errno(EINVAL
));
215 if (valid_usr_range(address
, length
, 0, as
, as
->a_userlimit
) !=
217 return (set_errno(ENOMEM
));
219 error
= as_ctl(as
, address
, length
, MC_UNLOCK
, 0, 0, NULL
, 0);
221 (void) set_errno(error
);
227 gfxp_convert_addr(paddr_t paddr
)
229 return ((gfx_maddr_t
)paddr
);
233 * Support getting VA space separately from pages
237 * A little like gfxp_map_kernel_space, but
238 * just the vmem_alloc part.
241 gfxp_alloc_kernel_space(size_t size
)
246 npages
= btopr(size
);
247 cvaddr
= vmem_alloc(heap_arena
, ptob(npages
), VM_NOSLEEP
);
252 * Like gfxp_unmap_kernel_space, but
253 * just the vmem_free part.
256 gfxp_free_kernel_space(caddr_t address
, size_t size
)
263 if (size
== 0 || address
== NULL
)
266 pgoffset
= (uintptr_t)address
& PAGEOFFSET
;
267 base
= (caddr_t
)address
- pgoffset
;
268 npages
= btopr(size
+ pgoffset
);
269 vmem_free(heap_arena
, base
, ptob(npages
));
273 * Like gfxp_map_kernel_space, but
274 * just the hat_devload part.
277 gfxp_load_kernel_space(uint64_t start
, size_t size
,
278 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
)