OSDN Git Service

ttm: make sure userspace can't destroy kernel create memory managers
[android-x86/external-libdrm.git] / shared-core / nv50_graph.c
1 /*
2  * Copyright (C) 2007 Ben Skeggs.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "drmP.h"
28 #include "drm.h"
29 #include "nouveau_drv.h"
30
31 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
32
33 static void
34 nv50_graph_init_reset(struct drm_device *dev)
35 {
36         struct drm_nouveau_private *dev_priv = dev->dev_private;
37         uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
38
39         DRM_DEBUG("\n");
40
41         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e);
42         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |  pmc_e);
43 }
44
45 static void
46 nv50_graph_init_intr(struct drm_device *dev)
47 {
48         struct drm_nouveau_private *dev_priv = dev->dev_private;
49
50         DRM_DEBUG("\n");
51         NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff);
52         NV_WRITE(0x400138, 0xffffffff);
53         NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff);
54 }
55
56 static void
57 nv50_graph_init_regs__nv(struct drm_device *dev)
58 {
59         struct drm_nouveau_private *dev_priv = dev->dev_private;
60
61         DRM_DEBUG("\n");
62
63         NV_WRITE(0x400804, 0xc0000000);
64         NV_WRITE(0x406800, 0xc0000000);
65         NV_WRITE(0x400c04, 0xc0000000);
66         NV_WRITE(0x401804, 0xc0000000);
67         NV_WRITE(0x405018, 0xc0000000);
68         NV_WRITE(0x402000, 0xc0000000);
69
70         NV_WRITE(0x400108, 0xffffffff);
71
72         NV_WRITE(0x400824, 0x00004000);
73         NV_WRITE(0x400500, 0x00010001);
74 }
75
76 static void
77 nv50_graph_init_regs(struct drm_device *dev)
78 {
79         struct drm_nouveau_private *dev_priv = dev->dev_private;
80
81         DRM_DEBUG("\n");
82
83         NV_WRITE(NV04_PGRAPH_DEBUG_3, (1<<2) /* HW_CONTEXT_SWITCH_ENABLED */);
84 }
85
86 static uint32_t nv84_ctx_voodoo[] = {
87         0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89,
88         0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff,
89         0x00700009, 0x0041634d, 0x00402944, 0x00402905, 0x0040290d, 0x00413e06,
90         0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000,
91         0x00700081, 0x00600004, 0x0050004a, 0x00216f40, 0x00600007, 0x00c02801,
92         0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020,
93         0x00600008, 0x0050004c, 0x00600009, 0x00413e45, 0x0041594d, 0x0070009d,
94         0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008,
95         0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006,
96         0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216f40, 0x00600007,
97         0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080,
98         0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200480, 0x00600007,
99         0x00300000, 0x00c000ff, 0x00c800ff, 0x00414907, 0x00202916, 0x008000ff,
100         0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f,
101         0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302,
102         0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f,
103         0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02,
104         0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407,
105         0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b,
106         0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040798c,
107         0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04,
108         0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65,
109         0x00131c80, 0x00121c84, 0x00141ca0, 0x00111ca5, 0x00131cc0, 0x00121cc4,
110         0x00141ce0, 0x00111ce5, 0x00131f00, 0x00191f40, 0x0040a1e0, 0x002001ed,
111         0x00600006, 0x00200044, 0x00102080, 0x001120c6, 0x001520c9, 0x001920d0,
112         0x00122100, 0x00122103, 0x00162200, 0x00122207, 0x00112280, 0x00112300,
113         0x00112302, 0x00122380, 0x0011238b, 0x00112394, 0x0011239c, 0x0040bee1,
114         0x00200254, 0x00600006, 0x00200044, 0x00102480, 0x0040af0f, 0x0040af4b,
115         0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040af8c,
116         0x005000cb, 0x00000000, 0x001124c6, 0x001524c9, 0x001924d0, 0x00122500,
117         0x00122503, 0x00162600, 0x00122607, 0x00112680, 0x00112700, 0x00112702,
118         0x00122780, 0x0011278b, 0x00112794, 0x0011279c, 0x0040d1e2, 0x002002bb,
119         0x00600006, 0x00200044, 0x00102880, 0x001128c6, 0x001528c9, 0x001928d0,
120         0x00122900, 0x00122903, 0x00162a00, 0x00122a07, 0x00112a80, 0x00112b00,
121         0x00112b02, 0x00122b80, 0x00112b8b, 0x00112b94, 0x00112b9c, 0x0040eee3,
122         0x00200322, 0x00600006, 0x00200044, 0x00102c80, 0x0040df0f, 0x0040df4b,
123         0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040df8c,
124         0x005000cb, 0x00000000, 0x00112cc6, 0x00152cc9, 0x00192cd0, 0x00122d00,
125         0x00122d03, 0x00162e00, 0x00122e07, 0x00112e80, 0x00112f00, 0x00112f02,
126         0x00122f80, 0x00112f8b, 0x00112f94, 0x00112f9c, 0x004101e4, 0x00200389,
127         0x00600006, 0x00200044, 0x00103080, 0x001130c6, 0x001530c9, 0x001930d0,
128         0x00123100, 0x00123103, 0x00163200, 0x00123207, 0x00113280, 0x00113300,
129         0x00113302, 0x00123380, 0x0011338b, 0x00113394, 0x0011339c, 0x00411ee5,
130         0x002003f0, 0x00600006, 0x00200044, 0x00103480, 0x00410f0f, 0x00410f4b,
131         0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x00410f8c,
132         0x005000cb, 0x00000000, 0x001134c6, 0x001534c9, 0x001934d0, 0x00123500,
133         0x00123503, 0x00163600, 0x00123607, 0x00113680, 0x00113700, 0x00113702,
134         0x00123780, 0x0011378b, 0x00113794, 0x0011379c, 0x00000000, 0x0041250f,
135         0x005000cb, 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x005000cb,
136         0x00412887, 0x0060000a, 0x00000000, 0x00413700, 0x007000a0, 0x00700080,
137         0x00200480, 0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb,
138         0x00700000, 0x00200000, 0x00600006, 0x00111bfe, 0x0041594d, 0x00700000,
139         0x00200000, 0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d,
140         0x00700081, 0x00600004, 0x0050004a, 0x00414388, 0x0060000b, 0x00200000,
141         0x00600006, 0x00700000, 0x0041590b, 0x00111bfd, 0x0040424d, 0x00202916,
142         0x008000fd, 0x005000cb, 0x00c00002, 0x00200480, 0x00600007, 0x00200160,
143         0x00800002, 0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb,
144         0x00404e4d, 0x0060000b, 0x0041574d, 0x00700001, 0x005000cf, 0x00700003,
145         0x00415e06, 0x00415f05, 0x0060000d, 0x00700005, 0x0070000d, 0x00700006,
146         0x0070000b, 0x0070000e, 0x0070001c, 0x0060000c, ~0
147 };
148  
149 static uint32_t nv86_ctx_voodoo[] = {
150         0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89, 
151         0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff, 
152         0x00700009, 0x0040dd4d, 0x00402944, 0x00402905, 0x0040290d, 0x0040b906, 
153         0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000, 
154         0x00700081, 0x00600004, 0x0050004a, 0x00216d80, 0x00600007, 0x00c02801, 
155         0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020, 
156         0x00600008, 0x0050004c, 0x00600009, 0x0040b945, 0x0040d44d, 0x0070009d, 
157         0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008, 
158         0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006, 
159         0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216d80, 0x00600007, 
160         0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080, 
161         0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200280, 0x00600007, 
162         0x00300000, 0x00c000ff, 0x00c800ff, 0x0040c407, 0x00202916, 0x008000ff, 
163         0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f, 
164         0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302, 
165         0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f, 
166         0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02, 
167         0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407, 
168         0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b, 
169         0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x0070008f, 0x0040798c, 
170         0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04, 
171         0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65, 
172         0x00131f00, 0x00191f40, 0x004099e0, 0x002001d9, 0x00600006, 0x00200044, 
173         0x00102080, 0x001120c6, 0x001520c9, 0x001920d0, 0x00122100, 0x00122103, 
174         0x00162200, 0x00122207, 0x00112280, 0x00112300, 0x00112302, 0x00122380, 
175         0x0011238b, 0x00112394, 0x0011239c, 0x00000000, 0x0040a00f, 0x005000cb, 
176         0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x005000cb, 0x0040a387, 
177         0x0060000a, 0x00000000, 0x0040b200, 0x007000a0, 0x00700080, 0x00200280, 
178         0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb, 0x00700000, 
179         0x00200000, 0x00600006, 0x00111bfe, 0x0040d44d, 0x00700000, 0x00200000, 
180         0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d, 0x00700081, 
181         0x00600004, 0x0050004a, 0x0040be88, 0x0060000b, 0x00200000, 0x00600006, 
182         0x00700000, 0x0040d40b, 0x00111bfd, 0x0040424d, 0x00202916, 0x008000fd, 
183         0x005000cb, 0x00c00002, 0x00200280, 0x00600007, 0x00200160, 0x00800002, 
184         0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb, 0x00404e4d, 
185         0x0060000b, 0x0040d24d, 0x00700001, 0x00700003, 0x0040d806, 0x0040d905, 
186         0x0060000d, 0x00700005, 0x0070000d, 0x00700006, 0x0070000b, 0x0070000e, 
187         0x0070001c, 0x0060000c, ~0
188 };
189
190 static int
191 nv50_graph_init_ctxctl(struct drm_device *dev)
192 {
193         struct drm_nouveau_private *dev_priv = dev->dev_private;
194         uint32_t *voodoo = NULL;
195
196         DRM_DEBUG("\n");
197
198         switch (dev_priv->chipset) {
199         case 0x84:
200                 voodoo = nv84_ctx_voodoo;
201                 break;
202         case 0x86:
203                 voodoo = nv86_ctx_voodoo;
204                 break;
205         default:
206                 DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset);
207                 return -EINVAL;
208         }
209
210         NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
211         while (*voodoo != ~0) {
212                 NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo);
213                 voodoo++;
214         }
215
216         NV_WRITE(0x400320, 4);
217         NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0);
218         NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
219
220         return 0;
221 }
222
223 int
224 nv50_graph_init(struct drm_device *dev)
225 {
226         int ret;
227
228         DRM_DEBUG("\n");
229
230         nv50_graph_init_reset(dev);
231         nv50_graph_init_intr(dev);
232         nv50_graph_init_regs__nv(dev);
233         nv50_graph_init_regs(dev);
234
235         ret = nv50_graph_init_ctxctl(dev);
236         if (ret)
237                 return ret;
238
239         return 0;
240 }
241
242 void
243 nv50_graph_takedown(struct drm_device *dev)
244 {
245         DRM_DEBUG("\n");
246 }
247
248 int
249 nv50_graph_create_context(struct nouveau_channel *chan)
250 {
251         struct drm_device *dev = chan->dev;
252         struct drm_nouveau_private *dev_priv = dev->dev_private;
253         struct nouveau_engine *engine = &dev_priv->Engine;
254         struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
255         int grctx_size = 0x60000, hdr;
256         int ret;
257
258         DRM_DEBUG("ch%d\n", chan->id);
259
260         ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
261                                      NVOBJ_FLAG_ZERO_ALLOC |
262                                      NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
263         if (ret)
264                 return ret;
265
266         hdr = IS_G80 ? 0x200 : 0x20;
267         INSTANCE_WR(ramin, (hdr + 0x00)/4, 0x00190002);
268         INSTANCE_WR(ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
269                                            grctx_size - 1);
270         INSTANCE_WR(ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
271         INSTANCE_WR(ramin, (hdr + 0x0c)/4, 0);
272         INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
273         INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
274
275         ret = engine->graph.load_context(chan);
276         if (ret) {
277                 DRM_ERROR("Error hacking up initial context: %d\n", ret);
278                 return ret;
279         }
280
281         INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x00000/4,
282                     chan->ramin->instance >> 12);
283         INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x0011c/4, 0x00000002);
284
285         return 0;
286 }
287
288 void
289 nv50_graph_destroy_context(struct nouveau_channel *chan)
290 {
291         struct drm_device *dev = chan->dev;
292         struct drm_nouveau_private *dev_priv = dev->dev_private;
293         int i, hdr;
294
295         DRM_DEBUG("ch%d\n", chan->id);
296
297         hdr = IS_G80 ? 0x200 : 0x20;
298         for (i=hdr; i<hdr+24; i+=4)
299                 INSTANCE_WR(chan->ramin->gpuobj, i/4, 0);
300
301         nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
302 }
303
304 static int
305 nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
306 {
307         struct drm_nouveau_private *dev_priv = dev->dev_private;
308         uint32_t old_cp, tv = 20000;
309         int i;
310
311         DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save);
312
313         old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
314         NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
315         NV_WRITE(0x400824, NV_READ(0x400824) |
316                  (save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
317                          NV40_PGRAPH_CTXCTL_0310_XFER_LOAD));
318         NV_WRITE(NV40_PGRAPH_CTXCTL_0304, NV40_PGRAPH_CTXCTL_0304_XFER_CTX);
319
320         for (i = 0; i < tv; i++) {
321                 if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0)
322                         break;
323         }
324         NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
325
326         if (i == tv) {
327                 DRM_ERROR("failed: inst=0x%08x save=%d\n", inst, save);
328                 DRM_ERROR("0x40030C = 0x%08x\n",
329                           NV_READ(NV40_PGRAPH_CTXCTL_030C));
330                 return -EBUSY;
331         }
332
333         return 0;
334 }
335
336 int
337 nv50_graph_load_context(struct nouveau_channel *chan)
338 {
339         struct drm_device *dev = chan->dev;
340         struct drm_nouveau_private *dev_priv = dev->dev_private;
341         uint32_t inst = chan->ramin->instance >> 12;
342         int ret; (void)ret;
343
344         DRM_DEBUG("ch%d\n", chan->id);
345
346 #if 0
347         if ((ret = nv50_graph_transfer_context(dev, inst, 0)))
348                 return ret;
349 #endif
350
351         NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
352         NV_WRITE(0x400320, 4);
353         NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst | (1<<31));
354
355         return 0;
356 }
357
358 int
359 nv50_graph_save_context(struct nouveau_channel *chan)
360 {
361         struct drm_device *dev = chan->dev;
362         uint32_t inst = chan->ramin->instance >> 12;
363
364         DRM_DEBUG("ch%d\n", chan->id);
365
366         return nv50_graph_transfer_context(dev, inst, 1);
367 }