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/vm.h>
32 struct nv50_vmmgr_priv
{
33 struct nouveau_vmmgr 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
->vmm
)->ram
.stolen
) {
90 phys
+= nouveau_fb(vma
->vm
->vmm
)->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 nouveau_engine
*engine
;
157 for (i
= 0; i
< NVDEV_SUBDEV_NR
; i
++) {
158 if (atomic_read(&vm
->engref
[i
])) {
159 engine
= nouveau_engine(vm
->vmm
, i
);
160 if (engine
&& engine
->tlb_flush
)
161 engine
->tlb_flush(engine
);
167 nv50_vm_flush_engine(struct nouveau_subdev
*subdev
, int engine
)
169 struct nv50_vmmgr_priv
*priv
= (void *)nouveau_vmmgr(subdev
);
172 spin_lock_irqsave(&priv
->lock
, flags
);
173 nv_wr32(subdev
, 0x100c80, (engine
<< 16) | 1);
174 if (!nv_wait(subdev
, 0x100c80, 0x00000001, 0x00000000))
175 nv_error(subdev
, "vm flush timeout: engine %d\n", engine
);
176 spin_unlock_irqrestore(&priv
->lock
, flags
);
180 nv50_vm_create(struct nouveau_vmmgr
*vmm
, u64 offset
, u64 length
,
181 u64 mm_offset
, struct nouveau_vm
**pvm
)
183 u32 block
= (1 << (vmm
->pgt_bits
+ 12));
187 return nouveau_vm_create(vmm
, offset
, length
, mm_offset
, block
, pvm
);
191 nv50_vmmgr_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
192 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
193 struct nouveau_object
**pobject
)
195 struct nv50_vmmgr_priv
*priv
;
198 ret
= nouveau_vmmgr_create(parent
, engine
, oclass
, "VM", "vm", &priv
);
199 *pobject
= nv_object(priv
);
203 priv
->base
.limit
= 1ULL << 40;
204 priv
->base
.pgt_bits
= 29 - 12;
205 priv
->base
.spg_shift
= 12;
206 priv
->base
.lpg_shift
= 16;
207 priv
->base
.create
= nv50_vm_create
;
208 priv
->base
.map_pgt
= nv50_vm_map_pgt
;
209 priv
->base
.map
= nv50_vm_map
;
210 priv
->base
.map_sg
= nv50_vm_map_sg
;
211 priv
->base
.unmap
= nv50_vm_unmap
;
212 priv
->base
.flush
= nv50_vm_flush
;
213 spin_lock_init(&priv
->lock
);
217 struct nouveau_oclass
218 nv50_vmmgr_oclass
= {
219 .handle
= NV_SUBDEV(VM
, 0x50),
220 .ofuncs
= &(struct nouveau_ofuncs
) {
221 .ctor
= nv50_vmmgr_ctor
,
222 .dtor
= _nouveau_vmmgr_dtor
,
223 .init
= _nouveau_vmmgr_init
,
224 .fini
= _nouveau_vmmgr_fini
,
This page took 0.035329 seconds and 5 git commands to generate.