2 * Copyright 2010 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <core/device.h>
26 #include <core/gpuobj.h>
28 #include <subdev/timer.h>
29 #include <subdev/fb.h>
30 #include <subdev/bar.h>
31 #include <subdev/mmu.h>
33 struct nv50_mmu_priv
{
34 struct nouveau_mmu base
;
38 nv50_vm_map_pgt(struct nouveau_gpuobj
*pgd
, u32 pde
,
39 struct nouveau_gpuobj
*pgt
[2])
41 u64 phys
= 0xdeadcafe00000000ULL
;
45 phys
= 0x00000003 | pgt
[0]->addr
; /* present, 4KiB pages */
46 coverage
= (pgt
[0]->size
>> 3) << 12;
49 phys
= 0x00000001 | pgt
[1]->addr
; /* present */
50 coverage
= (pgt
[1]->size
>> 3) << 16;
54 if (coverage
<= 32 * 1024 * 1024)
56 else if (coverage
<= 64 * 1024 * 1024)
58 else if (coverage
<= 128 * 1024 * 1024)
62 nv_wo32(pgd
, (pde
* 8) + 0, lower_32_bits(phys
));
63 nv_wo32(pgd
, (pde
* 8) + 4, upper_32_bits(phys
));
67 vm_addr(struct nouveau_vma
*vma
, u64 phys
, u32 memtype
, u32 target
)
69 phys
|= 1; /* present */
70 phys
|= (u64
)memtype
<< 40;
72 if (vma
->access
& NV_MEM_ACCESS_SYS
)
74 if (!(vma
->access
& NV_MEM_ACCESS_WO
))
80 nv50_vm_map(struct nouveau_vma
*vma
, struct nouveau_gpuobj
*pgt
,
81 struct nouveau_mem
*mem
, u32 pte
, u32 cnt
, u64 phys
, u64 delta
)
83 u32 comp
= (mem
->memtype
& 0x180) >> 7;
87 /* IGPs don't have real VRAM, re-target to stolen system memory */
89 if (nouveau_fb(vma
->vm
->mmu
)->ram
->stolen
) {
90 phys
+= nouveau_fb(vma
->vm
->mmu
)->ram
->stolen
;
94 phys
= vm_addr(vma
, phys
, mem
->memtype
, target
);
99 u32 offset_h
= upper_32_bits(phys
);
100 u32 offset_l
= lower_32_bits(phys
);
102 for (i
= 7; i
>= 0; i
--) {
103 block
= 1 << (i
+ 3);
104 if (cnt
>= block
&& !(pte
& (block
- 1)))
107 offset_l
|= (i
<< 7);
109 phys
+= block
<< (vma
->node
->type
- 3);
112 u32 tag
= mem
->tag
->offset
+ ((delta
>> 16) * comp
);
113 offset_h
|= (tag
<< 17);
114 delta
+= block
<< (vma
->node
->type
- 3);
118 nv_wo32(pgt
, pte
+ 0, offset_l
);
119 nv_wo32(pgt
, pte
+ 4, offset_h
);
127 nv50_vm_map_sg(struct nouveau_vma
*vma
, struct nouveau_gpuobj
*pgt
,
128 struct nouveau_mem
*mem
, u32 pte
, u32 cnt
, dma_addr_t
*list
)
130 u32 target
= (vma
->access
& NV_MEM_ACCESS_NOSNOOP
) ? 3 : 2;
133 u64 phys
= vm_addr(vma
, (u64
)*list
++, mem
->memtype
, target
);
134 nv_wo32(pgt
, pte
+ 0, lower_32_bits(phys
));
135 nv_wo32(pgt
, pte
+ 4, upper_32_bits(phys
));
141 nv50_vm_unmap(struct nouveau_gpuobj
*pgt
, u32 pte
, u32 cnt
)
145 nv_wo32(pgt
, pte
+ 0, 0x00000000);
146 nv_wo32(pgt
, pte
+ 4, 0x00000000);
152 nv50_vm_flush(struct nouveau_vm
*vm
)
154 struct nv50_mmu_priv
*priv
= (void *)vm
->mmu
;
155 struct nouveau_bar
*bar
= nouveau_bar(priv
);
156 struct nouveau_engine
*engine
;
161 mutex_lock(&nv_subdev(priv
)->mutex
);
162 for (i
= 0; i
< NVDEV_SUBDEV_NR
; i
++) {
163 if (!atomic_read(&vm
->engref
[i
]))
166 /* unfortunate hw bug workaround... */
167 engine
= nouveau_engine(priv
, i
);
168 if (engine
&& engine
->tlb_flush
) {
169 engine
->tlb_flush(engine
);
174 case NVDEV_ENGINE_GR
: vme
= 0x00; break;
175 case NVDEV_ENGINE_VP
:
176 case NVDEV_ENGINE_MSPDEC
: vme
= 0x01; break;
177 case NVDEV_SUBDEV_BAR
: vme
= 0x06; break;
178 case NVDEV_ENGINE_MSPPP
:
179 case NVDEV_ENGINE_MPEG
: vme
= 0x08; break;
180 case NVDEV_ENGINE_BSP
:
181 case NVDEV_ENGINE_MSVLD
: vme
= 0x09; break;
182 case NVDEV_ENGINE_CIPHER
:
183 case NVDEV_ENGINE_SEC
: vme
= 0x0a; break;
184 case NVDEV_ENGINE_CE0
: vme
= 0x0d; break;
189 nv_wr32(priv
, 0x100c80, (vme
<< 16) | 1);
190 if (!nv_wait(priv
, 0x100c80, 0x00000001, 0x00000000))
191 nv_error(priv
, "vm flush timeout: engine %d\n", vme
);
193 mutex_unlock(&nv_subdev(priv
)->mutex
);
197 nv50_vm_create(struct nouveau_mmu
*mmu
, u64 offset
, u64 length
,
198 u64 mm_offset
, struct nouveau_vm
**pvm
)
200 u32 block
= (1 << (mmu
->pgt_bits
+ 12));
204 return nouveau_vm_create(mmu
, offset
, length
, mm_offset
, block
, pvm
);
208 nv50_mmu_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
209 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
210 struct nouveau_object
**pobject
)
212 struct nv50_mmu_priv
*priv
;
215 ret
= nouveau_mmu_create(parent
, engine
, oclass
, "VM", "vm", &priv
);
216 *pobject
= nv_object(priv
);
220 priv
->base
.limit
= 1ULL << 40;
221 priv
->base
.dma_bits
= 40;
222 priv
->base
.pgt_bits
= 29 - 12;
223 priv
->base
.spg_shift
= 12;
224 priv
->base
.lpg_shift
= 16;
225 priv
->base
.create
= nv50_vm_create
;
226 priv
->base
.map_pgt
= nv50_vm_map_pgt
;
227 priv
->base
.map
= nv50_vm_map
;
228 priv
->base
.map_sg
= nv50_vm_map_sg
;
229 priv
->base
.unmap
= nv50_vm_unmap
;
230 priv
->base
.flush
= nv50_vm_flush
;
234 struct nouveau_oclass
236 .handle
= NV_SUBDEV(MMU
, 0x50),
237 .ofuncs
= &(struct nouveau_ofuncs
) {
238 .ctor
= nv50_mmu_ctor
,
239 .dtor
= _nouveau_mmu_dtor
,
240 .init
= _nouveau_mmu_init
,
241 .fini
= _nouveau_mmu_fini
,
This page took 0.057734 seconds and 5 git commands to generate.