blob: 4e2cadcdf144c28763961934ff5fb3cfb87f7baa [file] [log] [blame]
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001/*
2 * Copyright 2010 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Dave Airlie
25 * Alex Deucher
26 * Jerome Glisse
27 */
28#include "drmP.h"
29#include "radeon.h"
30#include "evergreend.h"
31#include "evergreen_reg_safe.h"
Alex Deucherc175ca92011-03-02 20:07:37 -050032#include "cayman_reg_safe.h"
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040033
34static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
35 struct radeon_cs_reloc **cs_reloc);
36
37struct evergreen_cs_track {
38 u32 group_size;
39 u32 nbanks;
40 u32 npipes;
Alex Deucherf3a71df2011-11-28 14:49:28 -050041 u32 row_size;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040042 /* value we track */
43 u32 nsamples;
44 u32 cb_color_base_last[12];
45 struct radeon_bo *cb_color_bo[12];
46 u32 cb_color_bo_offset[12];
47 struct radeon_bo *cb_color_fmask_bo[8];
48 struct radeon_bo *cb_color_cmask_bo[8];
49 u32 cb_color_info[12];
50 u32 cb_color_view[12];
51 u32 cb_color_pitch_idx[12];
52 u32 cb_color_slice_idx[12];
53 u32 cb_color_dim_idx[12];
54 u32 cb_color_dim[12];
55 u32 cb_color_pitch[12];
56 u32 cb_color_slice[12];
57 u32 cb_color_cmask_slice[8];
58 u32 cb_color_fmask_slice[8];
59 u32 cb_target_mask;
60 u32 cb_shader_mask;
61 u32 vgt_strmout_config;
62 u32 vgt_strmout_buffer_config;
Marek Olšákdd220a02012-01-27 12:17:59 -050063 struct radeon_bo *vgt_strmout_bo[4];
64 u64 vgt_strmout_bo_mc[4];
65 u32 vgt_strmout_bo_offset[4];
66 u32 vgt_strmout_size[4];
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040067 u32 db_depth_control;
68 u32 db_depth_view;
69 u32 db_depth_size;
70 u32 db_depth_size_idx;
71 u32 db_z_info;
72 u32 db_z_idx;
73 u32 db_z_read_offset;
74 u32 db_z_write_offset;
75 struct radeon_bo *db_z_read_bo;
76 struct radeon_bo *db_z_write_bo;
77 u32 db_s_info;
78 u32 db_s_idx;
79 u32 db_s_read_offset;
80 u32 db_s_write_offset;
81 struct radeon_bo *db_s_read_bo;
82 struct radeon_bo *db_s_write_bo;
83};
84
Alex Deucherf3a71df2011-11-28 14:49:28 -050085static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
86{
87 if (tiling_flags & RADEON_TILING_MACRO)
88 return ARRAY_2D_TILED_THIN1;
89 else if (tiling_flags & RADEON_TILING_MICRO)
90 return ARRAY_1D_TILED_THIN1;
91 else
92 return ARRAY_LINEAR_GENERAL;
93}
94
95static u32 evergreen_cs_get_num_banks(u32 nbanks)
96{
97 switch (nbanks) {
98 case 2:
99 return ADDR_SURF_2_BANK;
100 case 4:
101 return ADDR_SURF_4_BANK;
102 case 8:
103 default:
104 return ADDR_SURF_8_BANK;
105 case 16:
106 return ADDR_SURF_16_BANK;
107 }
108}
109
110static u32 evergreen_cs_get_tile_split(u32 row_size)
111{
112 switch (row_size) {
113 case 1:
114 default:
115 return ADDR_SURF_TILE_SPLIT_1KB;
116 case 2:
117 return ADDR_SURF_TILE_SPLIT_2KB;
118 case 4:
119 return ADDR_SURF_TILE_SPLIT_4KB;
120 }
121}
122
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400123static void evergreen_cs_track_init(struct evergreen_cs_track *track)
124{
125 int i;
126
127 for (i = 0; i < 8; i++) {
128 track->cb_color_fmask_bo[i] = NULL;
129 track->cb_color_cmask_bo[i] = NULL;
130 track->cb_color_cmask_slice[i] = 0;
131 track->cb_color_fmask_slice[i] = 0;
132 }
133
134 for (i = 0; i < 12; i++) {
135 track->cb_color_base_last[i] = 0;
136 track->cb_color_bo[i] = NULL;
137 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
138 track->cb_color_info[i] = 0;
139 track->cb_color_view[i] = 0;
140 track->cb_color_pitch_idx[i] = 0;
141 track->cb_color_slice_idx[i] = 0;
142 track->cb_color_dim[i] = 0;
143 track->cb_color_pitch[i] = 0;
144 track->cb_color_slice[i] = 0;
145 track->cb_color_dim[i] = 0;
146 }
147 track->cb_target_mask = 0xFFFFFFFF;
148 track->cb_shader_mask = 0xFFFFFFFF;
149
150 track->db_depth_view = 0xFFFFC000;
151 track->db_depth_size = 0xFFFFFFFF;
152 track->db_depth_size_idx = 0;
153 track->db_depth_control = 0xFFFFFFFF;
154 track->db_z_info = 0xFFFFFFFF;
155 track->db_z_idx = 0xFFFFFFFF;
156 track->db_z_read_offset = 0xFFFFFFFF;
157 track->db_z_write_offset = 0xFFFFFFFF;
158 track->db_z_read_bo = NULL;
159 track->db_z_write_bo = NULL;
160 track->db_s_info = 0xFFFFFFFF;
161 track->db_s_idx = 0xFFFFFFFF;
162 track->db_s_read_offset = 0xFFFFFFFF;
163 track->db_s_write_offset = 0xFFFFFFFF;
164 track->db_s_read_bo = NULL;
165 track->db_s_write_bo = NULL;
Marek Olšákdd220a02012-01-27 12:17:59 -0500166
167 for (i = 0; i < 4; i++) {
168 track->vgt_strmout_size[i] = 0;
169 track->vgt_strmout_bo[i] = NULL;
170 track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
171 track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
172 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400173}
174
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400175static int evergreen_cs_track_check(struct radeon_cs_parser *p)
176{
177 struct evergreen_cs_track *track = p->track;
Marek Olšákdd220a02012-01-27 12:17:59 -0500178 int i, j;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400179
Marek Olšákdd220a02012-01-27 12:17:59 -0500180 /* check streamout */
181 for (i = 0; i < 4; i++) {
182 if (track->vgt_strmout_config & (1 << i)) {
183 for (j = 0; j < 4; j++) {
184 if ((track->vgt_strmout_buffer_config >> (i * 4)) & (1 << j)) {
185 if (track->vgt_strmout_bo[j]) {
186 u64 offset = (u64)track->vgt_strmout_bo_offset[j] +
187 (u64)track->vgt_strmout_size[j];
188 if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
189 DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
190 j, offset,
191 radeon_bo_size(track->vgt_strmout_bo[j]));
192 return -EINVAL;
193 }
194 } else {
195 dev_warn(p->dev, "No buffer for streamout %d\n", j);
196 return -EINVAL;
197 }
198 }
199 }
200 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400201 }
202
203 /* XXX fill in */
204 return 0;
205}
206
207/**
208 * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
209 * @parser: parser structure holding parsing context.
210 * @pkt: where to store packet informations
211 *
212 * Assume that chunk_ib_index is properly set. Will return -EINVAL
213 * if packet is bigger than remaining ib size. or if packets is unknown.
214 **/
215int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
216 struct radeon_cs_packet *pkt,
217 unsigned idx)
218{
219 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
220 uint32_t header;
221
222 if (idx >= ib_chunk->length_dw) {
223 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
224 idx, ib_chunk->length_dw);
225 return -EINVAL;
226 }
227 header = radeon_get_ib_value(p, idx);
228 pkt->idx = idx;
229 pkt->type = CP_PACKET_GET_TYPE(header);
230 pkt->count = CP_PACKET_GET_COUNT(header);
231 pkt->one_reg_wr = 0;
232 switch (pkt->type) {
233 case PACKET_TYPE0:
234 pkt->reg = CP_PACKET0_GET_REG(header);
235 break;
236 case PACKET_TYPE3:
237 pkt->opcode = CP_PACKET3_GET_OPCODE(header);
238 break;
239 case PACKET_TYPE2:
240 pkt->count = -1;
241 break;
242 default:
243 DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
244 return -EINVAL;
245 }
246 if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
247 DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
248 pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
249 return -EINVAL;
250 }
251 return 0;
252}
253
254/**
255 * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
256 * @parser: parser structure holding parsing context.
257 * @data: pointer to relocation data
258 * @offset_start: starting offset
259 * @offset_mask: offset mask (to align start offset on)
260 * @reloc: reloc informations
261 *
262 * Check next packet is relocation packet3, do bo validation and compute
263 * GPU offset using the provided start.
264 **/
265static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
266 struct radeon_cs_reloc **cs_reloc)
267{
268 struct radeon_cs_chunk *relocs_chunk;
269 struct radeon_cs_packet p3reloc;
270 unsigned idx;
271 int r;
272
273 if (p->chunk_relocs_idx == -1) {
274 DRM_ERROR("No relocation chunk !\n");
275 return -EINVAL;
276 }
277 *cs_reloc = NULL;
278 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
279 r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
280 if (r) {
281 return r;
282 }
283 p->idx += p3reloc.count + 2;
284 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
285 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
286 p3reloc.idx);
287 return -EINVAL;
288 }
289 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
290 if (idx >= relocs_chunk->length_dw) {
291 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
292 idx, relocs_chunk->length_dw);
293 return -EINVAL;
294 }
295 /* FIXME: we assume reloc size is 4 dwords */
296 *cs_reloc = p->relocs_ptr[(idx / 4)];
297 return 0;
298}
299
300/**
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400301 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
302 * @parser: parser structure holding parsing context.
303 *
304 * Userspace sends a special sequence for VLINE waits.
305 * PACKET0 - VLINE_START_END + value
306 * PACKET3 - WAIT_REG_MEM poll vline status reg
307 * RELOC (P3) - crtc_id in reloc.
308 *
309 * This function parses this and relocates the VLINE START END
310 * and WAIT_REG_MEM packets to the correct crtc.
311 * It also detects a switched off crtc and nulls out the
312 * wait in that case.
313 */
314static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
315{
316 struct drm_mode_object *obj;
317 struct drm_crtc *crtc;
318 struct radeon_crtc *radeon_crtc;
319 struct radeon_cs_packet p3reloc, wait_reg_mem;
320 int crtc_id;
321 int r;
322 uint32_t header, h_idx, reg, wait_reg_mem_info;
323 volatile uint32_t *ib;
324
325 ib = p->ib->ptr;
326
327 /* parse the WAIT_REG_MEM */
328 r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
329 if (r)
330 return r;
331
332 /* check its a WAIT_REG_MEM */
333 if (wait_reg_mem.type != PACKET_TYPE3 ||
334 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
335 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100336 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400337 }
338
339 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
340 /* bit 4 is reg (0) or mem (1) */
341 if (wait_reg_mem_info & 0x10) {
342 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100343 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400344 }
345 /* waiting for value to be equal */
346 if ((wait_reg_mem_info & 0x7) != 0x3) {
347 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100348 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400349 }
350 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
351 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100352 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400353 }
354
355 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
356 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100357 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400358 }
359
360 /* jump over the NOP */
361 r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
362 if (r)
363 return r;
364
365 h_idx = p->idx - 2;
366 p->idx += wait_reg_mem.count + 2;
367 p->idx += p3reloc.count + 2;
368
369 header = radeon_get_ib_value(p, h_idx);
370 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
371 reg = CP_PACKET0_GET_REG(header);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400372 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
373 if (!obj) {
374 DRM_ERROR("cannot find crtc %d\n", crtc_id);
Paul Bollea3a88a62011-03-16 22:10:06 +0100375 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400376 }
377 crtc = obj_to_crtc(obj);
378 radeon_crtc = to_radeon_crtc(crtc);
379 crtc_id = radeon_crtc->crtc_id;
380
381 if (!crtc->enabled) {
382 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
383 ib[h_idx + 2] = PACKET2(0);
384 ib[h_idx + 3] = PACKET2(0);
385 ib[h_idx + 4] = PACKET2(0);
386 ib[h_idx + 5] = PACKET2(0);
387 ib[h_idx + 6] = PACKET2(0);
388 ib[h_idx + 7] = PACKET2(0);
389 ib[h_idx + 8] = PACKET2(0);
390 } else {
391 switch (reg) {
392 case EVERGREEN_VLINE_START_END:
393 header &= ~R600_CP_PACKET0_REG_MASK;
394 header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
395 ib[h_idx] = header;
396 ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
397 break;
398 default:
399 DRM_ERROR("unknown crtc reloc\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100400 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400401 }
402 }
Paul Bollea3a88a62011-03-16 22:10:06 +0100403 return 0;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400404}
405
406static int evergreen_packet0_check(struct radeon_cs_parser *p,
407 struct radeon_cs_packet *pkt,
408 unsigned idx, unsigned reg)
409{
410 int r;
411
412 switch (reg) {
413 case EVERGREEN_VLINE_START_END:
414 r = evergreen_cs_packet_parse_vline(p);
415 if (r) {
416 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
417 idx, reg);
418 return r;
419 }
420 break;
421 default:
422 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
423 reg, idx);
424 return -EINVAL;
425 }
426 return 0;
427}
428
429static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
430 struct radeon_cs_packet *pkt)
431{
432 unsigned reg, i;
433 unsigned idx;
434 int r;
435
436 idx = pkt->idx + 1;
437 reg = pkt->reg;
438 for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
439 r = evergreen_packet0_check(p, pkt, idx, reg);
440 if (r) {
441 return r;
442 }
443 }
444 return 0;
445}
446
447/**
448 * evergreen_cs_check_reg() - check if register is authorized or not
449 * @parser: parser structure holding parsing context
450 * @reg: register we are testing
451 * @idx: index into the cs buffer
452 *
453 * This function will test against evergreen_reg_safe_bm and return 0
454 * if register is safe. If register is not flag as safe this function
455 * will test it against a list of register needind special handling.
456 */
Andi Kleen488479e2011-10-13 16:08:41 -0700457static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400458{
459 struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
460 struct radeon_cs_reloc *reloc;
Alex Deucherc175ca92011-03-02 20:07:37 -0500461 u32 last_reg;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400462 u32 m, i, tmp, *ib;
463 int r;
464
Alex Deucherc175ca92011-03-02 20:07:37 -0500465 if (p->rdev->family >= CHIP_CAYMAN)
466 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
467 else
468 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
469
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400470 i = (reg >> 7);
Dan Carpenter88498832011-07-27 09:53:40 +0000471 if (i >= last_reg) {
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400472 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
473 return -EINVAL;
474 }
475 m = 1 << ((reg >> 2) & 31);
Alex Deucherc175ca92011-03-02 20:07:37 -0500476 if (p->rdev->family >= CHIP_CAYMAN) {
477 if (!(cayman_reg_safe_bm[i] & m))
478 return 0;
479 } else {
480 if (!(evergreen_reg_safe_bm[i] & m))
481 return 0;
482 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400483 ib = p->ib->ptr;
484 switch (reg) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300485 /* force following reg to 0 in an attempt to disable out buffer
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400486 * which will need us to better understand how it works to perform
487 * security check on it (Jerome)
488 */
489 case SQ_ESGS_RING_SIZE:
490 case SQ_GSVS_RING_SIZE:
491 case SQ_ESTMP_RING_SIZE:
492 case SQ_GSTMP_RING_SIZE:
493 case SQ_HSTMP_RING_SIZE:
494 case SQ_LSTMP_RING_SIZE:
495 case SQ_PSTMP_RING_SIZE:
496 case SQ_VSTMP_RING_SIZE:
497 case SQ_ESGS_RING_ITEMSIZE:
498 case SQ_ESTMP_RING_ITEMSIZE:
499 case SQ_GSTMP_RING_ITEMSIZE:
500 case SQ_GSVS_RING_ITEMSIZE:
501 case SQ_GS_VERT_ITEMSIZE:
502 case SQ_GS_VERT_ITEMSIZE_1:
503 case SQ_GS_VERT_ITEMSIZE_2:
504 case SQ_GS_VERT_ITEMSIZE_3:
505 case SQ_GSVS_RING_OFFSET_1:
506 case SQ_GSVS_RING_OFFSET_2:
507 case SQ_GSVS_RING_OFFSET_3:
508 case SQ_HSTMP_RING_ITEMSIZE:
509 case SQ_LSTMP_RING_ITEMSIZE:
510 case SQ_PSTMP_RING_ITEMSIZE:
511 case SQ_VSTMP_RING_ITEMSIZE:
512 case VGT_TF_RING_SIZE:
513 /* get value to populate the IB don't remove */
Alex Deucher8aa75002011-03-02 20:07:40 -0500514 /*tmp =radeon_get_ib_value(p, idx);
515 ib[idx] = 0;*/
516 break;
517 case SQ_ESGS_RING_BASE:
518 case SQ_GSVS_RING_BASE:
519 case SQ_ESTMP_RING_BASE:
520 case SQ_GSTMP_RING_BASE:
521 case SQ_HSTMP_RING_BASE:
522 case SQ_LSTMP_RING_BASE:
523 case SQ_PSTMP_RING_BASE:
524 case SQ_VSTMP_RING_BASE:
525 r = evergreen_cs_packet_next_reloc(p, &reloc);
526 if (r) {
527 dev_warn(p->dev, "bad SET_CONTEXT_REG "
528 "0x%04X\n", reg);
529 return -EINVAL;
530 }
531 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400532 break;
533 case DB_DEPTH_CONTROL:
534 track->db_depth_control = radeon_get_ib_value(p, idx);
535 break;
Alex Deucherc175ca92011-03-02 20:07:37 -0500536 case CAYMAN_DB_EQAA:
537 if (p->rdev->family < CHIP_CAYMAN) {
538 dev_warn(p->dev, "bad SET_CONTEXT_REG "
539 "0x%04X\n", reg);
540 return -EINVAL;
541 }
542 break;
543 case CAYMAN_DB_DEPTH_INFO:
544 if (p->rdev->family < CHIP_CAYMAN) {
545 dev_warn(p->dev, "bad SET_CONTEXT_REG "
546 "0x%04X\n", reg);
547 return -EINVAL;
548 }
549 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400550 case DB_Z_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400551 track->db_z_info = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -0500552 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +0200553 r = evergreen_cs_packet_next_reloc(p, &reloc);
554 if (r) {
555 dev_warn(p->dev, "bad SET_CONTEXT_REG "
556 "0x%04X\n", reg);
557 return -EINVAL;
558 }
559 ib[idx] &= ~Z_ARRAY_MODE(0xf);
560 track->db_z_info &= ~Z_ARRAY_MODE(0xf);
Alex Deucherf3a71df2011-11-28 14:49:28 -0500561 ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
562 track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Marek Olšáke70f2242011-10-25 01:38:45 +0200563 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
Alex Deucherf3a71df2011-11-28 14:49:28 -0500564 ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
565 ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
Marek Olšáke70f2242011-10-25 01:38:45 +0200566 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400567 }
568 break;
569 case DB_STENCIL_INFO:
570 track->db_s_info = radeon_get_ib_value(p, idx);
571 break;
572 case DB_DEPTH_VIEW:
573 track->db_depth_view = radeon_get_ib_value(p, idx);
574 break;
575 case DB_DEPTH_SIZE:
576 track->db_depth_size = radeon_get_ib_value(p, idx);
577 track->db_depth_size_idx = idx;
578 break;
579 case DB_Z_READ_BASE:
580 r = evergreen_cs_packet_next_reloc(p, &reloc);
581 if (r) {
582 dev_warn(p->dev, "bad SET_CONTEXT_REG "
583 "0x%04X\n", reg);
584 return -EINVAL;
585 }
586 track->db_z_read_offset = radeon_get_ib_value(p, idx);
587 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
588 track->db_z_read_bo = reloc->robj;
589 break;
590 case DB_Z_WRITE_BASE:
591 r = evergreen_cs_packet_next_reloc(p, &reloc);
592 if (r) {
593 dev_warn(p->dev, "bad SET_CONTEXT_REG "
594 "0x%04X\n", reg);
595 return -EINVAL;
596 }
597 track->db_z_write_offset = radeon_get_ib_value(p, idx);
598 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
599 track->db_z_write_bo = reloc->robj;
600 break;
601 case DB_STENCIL_READ_BASE:
602 r = evergreen_cs_packet_next_reloc(p, &reloc);
603 if (r) {
604 dev_warn(p->dev, "bad SET_CONTEXT_REG "
605 "0x%04X\n", reg);
606 return -EINVAL;
607 }
608 track->db_s_read_offset = radeon_get_ib_value(p, idx);
609 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
610 track->db_s_read_bo = reloc->robj;
611 break;
612 case DB_STENCIL_WRITE_BASE:
613 r = evergreen_cs_packet_next_reloc(p, &reloc);
614 if (r) {
615 dev_warn(p->dev, "bad SET_CONTEXT_REG "
616 "0x%04X\n", reg);
617 return -EINVAL;
618 }
619 track->db_s_write_offset = radeon_get_ib_value(p, idx);
620 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
621 track->db_s_write_bo = reloc->robj;
622 break;
623 case VGT_STRMOUT_CONFIG:
624 track->vgt_strmout_config = radeon_get_ib_value(p, idx);
625 break;
626 case VGT_STRMOUT_BUFFER_CONFIG:
627 track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
628 break;
Marek Olšákdd220a02012-01-27 12:17:59 -0500629 case VGT_STRMOUT_BUFFER_BASE_0:
630 case VGT_STRMOUT_BUFFER_BASE_1:
631 case VGT_STRMOUT_BUFFER_BASE_2:
632 case VGT_STRMOUT_BUFFER_BASE_3:
633 r = evergreen_cs_packet_next_reloc(p, &reloc);
634 if (r) {
635 dev_warn(p->dev, "bad SET_CONTEXT_REG "
636 "0x%04X\n", reg);
637 return -EINVAL;
638 }
639 tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
640 track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
641 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
642 track->vgt_strmout_bo[tmp] = reloc->robj;
643 track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
644 break;
645 case VGT_STRMOUT_BUFFER_SIZE_0:
646 case VGT_STRMOUT_BUFFER_SIZE_1:
647 case VGT_STRMOUT_BUFFER_SIZE_2:
648 case VGT_STRMOUT_BUFFER_SIZE_3:
649 tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
650 /* size in register is DWs, convert to bytes */
651 track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
652 break;
653 case CP_COHER_BASE:
654 r = evergreen_cs_packet_next_reloc(p, &reloc);
655 if (r) {
656 dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
657 "0x%04X\n", reg);
658 return -EINVAL;
659 }
660 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400661 case CB_TARGET_MASK:
662 track->cb_target_mask = radeon_get_ib_value(p, idx);
663 break;
664 case CB_SHADER_MASK:
665 track->cb_shader_mask = radeon_get_ib_value(p, idx);
666 break;
667 case PA_SC_AA_CONFIG:
Alex Deucherc175ca92011-03-02 20:07:37 -0500668 if (p->rdev->family >= CHIP_CAYMAN) {
669 dev_warn(p->dev, "bad SET_CONTEXT_REG "
670 "0x%04X\n", reg);
671 return -EINVAL;
672 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400673 tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
674 track->nsamples = 1 << tmp;
675 break;
Alex Deucherc175ca92011-03-02 20:07:37 -0500676 case CAYMAN_PA_SC_AA_CONFIG:
677 if (p->rdev->family < CHIP_CAYMAN) {
678 dev_warn(p->dev, "bad SET_CONTEXT_REG "
679 "0x%04X\n", reg);
680 return -EINVAL;
681 }
682 tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
683 track->nsamples = 1 << tmp;
684 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400685 case CB_COLOR0_VIEW:
686 case CB_COLOR1_VIEW:
687 case CB_COLOR2_VIEW:
688 case CB_COLOR3_VIEW:
689 case CB_COLOR4_VIEW:
690 case CB_COLOR5_VIEW:
691 case CB_COLOR6_VIEW:
692 case CB_COLOR7_VIEW:
693 tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
694 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
695 break;
696 case CB_COLOR8_VIEW:
697 case CB_COLOR9_VIEW:
698 case CB_COLOR10_VIEW:
699 case CB_COLOR11_VIEW:
700 tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
701 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
702 break;
703 case CB_COLOR0_INFO:
704 case CB_COLOR1_INFO:
705 case CB_COLOR2_INFO:
706 case CB_COLOR3_INFO:
707 case CB_COLOR4_INFO:
708 case CB_COLOR5_INFO:
709 case CB_COLOR6_INFO:
710 case CB_COLOR7_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400711 tmp = (reg - CB_COLOR0_INFO) / 0x3c;
712 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -0500713 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +0200714 r = evergreen_cs_packet_next_reloc(p, &reloc);
715 if (r) {
716 dev_warn(p->dev, "bad SET_CONTEXT_REG "
717 "0x%04X\n", reg);
718 return -EINVAL;
719 }
Alex Deucherf3a71df2011-11-28 14:49:28 -0500720 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
721 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400722 }
723 break;
724 case CB_COLOR8_INFO:
725 case CB_COLOR9_INFO:
726 case CB_COLOR10_INFO:
727 case CB_COLOR11_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400728 tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
729 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -0500730 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +0200731 r = evergreen_cs_packet_next_reloc(p, &reloc);
732 if (r) {
733 dev_warn(p->dev, "bad SET_CONTEXT_REG "
734 "0x%04X\n", reg);
735 return -EINVAL;
736 }
Alex Deucherf3a71df2011-11-28 14:49:28 -0500737 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
738 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400739 }
740 break;
741 case CB_COLOR0_PITCH:
742 case CB_COLOR1_PITCH:
743 case CB_COLOR2_PITCH:
744 case CB_COLOR3_PITCH:
745 case CB_COLOR4_PITCH:
746 case CB_COLOR5_PITCH:
747 case CB_COLOR6_PITCH:
748 case CB_COLOR7_PITCH:
749 tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
750 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
751 track->cb_color_pitch_idx[tmp] = idx;
752 break;
753 case CB_COLOR8_PITCH:
754 case CB_COLOR9_PITCH:
755 case CB_COLOR10_PITCH:
756 case CB_COLOR11_PITCH:
757 tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
758 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
759 track->cb_color_pitch_idx[tmp] = idx;
760 break;
761 case CB_COLOR0_SLICE:
762 case CB_COLOR1_SLICE:
763 case CB_COLOR2_SLICE:
764 case CB_COLOR3_SLICE:
765 case CB_COLOR4_SLICE:
766 case CB_COLOR5_SLICE:
767 case CB_COLOR6_SLICE:
768 case CB_COLOR7_SLICE:
769 tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
770 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
771 track->cb_color_slice_idx[tmp] = idx;
772 break;
773 case CB_COLOR8_SLICE:
774 case CB_COLOR9_SLICE:
775 case CB_COLOR10_SLICE:
776 case CB_COLOR11_SLICE:
777 tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
778 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
779 track->cb_color_slice_idx[tmp] = idx;
780 break;
781 case CB_COLOR0_ATTRIB:
782 case CB_COLOR1_ATTRIB:
783 case CB_COLOR2_ATTRIB:
784 case CB_COLOR3_ATTRIB:
785 case CB_COLOR4_ATTRIB:
786 case CB_COLOR5_ATTRIB:
787 case CB_COLOR6_ATTRIB:
788 case CB_COLOR7_ATTRIB:
789 case CB_COLOR8_ATTRIB:
790 case CB_COLOR9_ATTRIB:
791 case CB_COLOR10_ATTRIB:
792 case CB_COLOR11_ATTRIB:
Alex Deucherf3a71df2011-11-28 14:49:28 -0500793 r = evergreen_cs_packet_next_reloc(p, &reloc);
794 if (r) {
795 dev_warn(p->dev, "bad SET_CONTEXT_REG "
796 "0x%04X\n", reg);
797 return -EINVAL;
798 }
799 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
800 ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
801 ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
802 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400803 break;
804 case CB_COLOR0_DIM:
805 case CB_COLOR1_DIM:
806 case CB_COLOR2_DIM:
807 case CB_COLOR3_DIM:
808 case CB_COLOR4_DIM:
809 case CB_COLOR5_DIM:
810 case CB_COLOR6_DIM:
811 case CB_COLOR7_DIM:
812 tmp = (reg - CB_COLOR0_DIM) / 0x3c;
813 track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
814 track->cb_color_dim_idx[tmp] = idx;
815 break;
816 case CB_COLOR8_DIM:
817 case CB_COLOR9_DIM:
818 case CB_COLOR10_DIM:
819 case CB_COLOR11_DIM:
820 tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
821 track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
822 track->cb_color_dim_idx[tmp] = idx;
823 break;
824 case CB_COLOR0_FMASK:
825 case CB_COLOR1_FMASK:
826 case CB_COLOR2_FMASK:
827 case CB_COLOR3_FMASK:
828 case CB_COLOR4_FMASK:
829 case CB_COLOR5_FMASK:
830 case CB_COLOR6_FMASK:
831 case CB_COLOR7_FMASK:
832 tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
833 r = evergreen_cs_packet_next_reloc(p, &reloc);
834 if (r) {
835 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
836 return -EINVAL;
837 }
838 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
839 track->cb_color_fmask_bo[tmp] = reloc->robj;
840 break;
841 case CB_COLOR0_CMASK:
842 case CB_COLOR1_CMASK:
843 case CB_COLOR2_CMASK:
844 case CB_COLOR3_CMASK:
845 case CB_COLOR4_CMASK:
846 case CB_COLOR5_CMASK:
847 case CB_COLOR6_CMASK:
848 case CB_COLOR7_CMASK:
849 tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
850 r = evergreen_cs_packet_next_reloc(p, &reloc);
851 if (r) {
852 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
853 return -EINVAL;
854 }
855 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
856 track->cb_color_cmask_bo[tmp] = reloc->robj;
857 break;
858 case CB_COLOR0_FMASK_SLICE:
859 case CB_COLOR1_FMASK_SLICE:
860 case CB_COLOR2_FMASK_SLICE:
861 case CB_COLOR3_FMASK_SLICE:
862 case CB_COLOR4_FMASK_SLICE:
863 case CB_COLOR5_FMASK_SLICE:
864 case CB_COLOR6_FMASK_SLICE:
865 case CB_COLOR7_FMASK_SLICE:
866 tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
867 track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
868 break;
869 case CB_COLOR0_CMASK_SLICE:
870 case CB_COLOR1_CMASK_SLICE:
871 case CB_COLOR2_CMASK_SLICE:
872 case CB_COLOR3_CMASK_SLICE:
873 case CB_COLOR4_CMASK_SLICE:
874 case CB_COLOR5_CMASK_SLICE:
875 case CB_COLOR6_CMASK_SLICE:
876 case CB_COLOR7_CMASK_SLICE:
877 tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
878 track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
879 break;
880 case CB_COLOR0_BASE:
881 case CB_COLOR1_BASE:
882 case CB_COLOR2_BASE:
883 case CB_COLOR3_BASE:
884 case CB_COLOR4_BASE:
885 case CB_COLOR5_BASE:
886 case CB_COLOR6_BASE:
887 case CB_COLOR7_BASE:
888 r = evergreen_cs_packet_next_reloc(p, &reloc);
889 if (r) {
890 dev_warn(p->dev, "bad SET_CONTEXT_REG "
891 "0x%04X\n", reg);
892 return -EINVAL;
893 }
894 tmp = (reg - CB_COLOR0_BASE) / 0x3c;
895 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
896 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
897 track->cb_color_base_last[tmp] = ib[idx];
898 track->cb_color_bo[tmp] = reloc->robj;
899 break;
900 case CB_COLOR8_BASE:
901 case CB_COLOR9_BASE:
902 case CB_COLOR10_BASE:
903 case CB_COLOR11_BASE:
904 r = evergreen_cs_packet_next_reloc(p, &reloc);
905 if (r) {
906 dev_warn(p->dev, "bad SET_CONTEXT_REG "
907 "0x%04X\n", reg);
908 return -EINVAL;
909 }
910 tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
911 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
912 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
913 track->cb_color_base_last[tmp] = ib[idx];
914 track->cb_color_bo[tmp] = reloc->robj;
915 break;
916 case CB_IMMED0_BASE:
917 case CB_IMMED1_BASE:
918 case CB_IMMED2_BASE:
919 case CB_IMMED3_BASE:
920 case CB_IMMED4_BASE:
921 case CB_IMMED5_BASE:
922 case CB_IMMED6_BASE:
923 case CB_IMMED7_BASE:
924 case CB_IMMED8_BASE:
925 case CB_IMMED9_BASE:
926 case CB_IMMED10_BASE:
927 case CB_IMMED11_BASE:
928 case DB_HTILE_DATA_BASE:
929 case SQ_PGM_START_FS:
930 case SQ_PGM_START_ES:
931 case SQ_PGM_START_VS:
932 case SQ_PGM_START_GS:
933 case SQ_PGM_START_PS:
934 case SQ_PGM_START_HS:
935 case SQ_PGM_START_LS:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400936 case SQ_CONST_MEM_BASE:
937 case SQ_ALU_CONST_CACHE_GS_0:
938 case SQ_ALU_CONST_CACHE_GS_1:
939 case SQ_ALU_CONST_CACHE_GS_2:
940 case SQ_ALU_CONST_CACHE_GS_3:
941 case SQ_ALU_CONST_CACHE_GS_4:
942 case SQ_ALU_CONST_CACHE_GS_5:
943 case SQ_ALU_CONST_CACHE_GS_6:
944 case SQ_ALU_CONST_CACHE_GS_7:
945 case SQ_ALU_CONST_CACHE_GS_8:
946 case SQ_ALU_CONST_CACHE_GS_9:
947 case SQ_ALU_CONST_CACHE_GS_10:
948 case SQ_ALU_CONST_CACHE_GS_11:
949 case SQ_ALU_CONST_CACHE_GS_12:
950 case SQ_ALU_CONST_CACHE_GS_13:
951 case SQ_ALU_CONST_CACHE_GS_14:
952 case SQ_ALU_CONST_CACHE_GS_15:
953 case SQ_ALU_CONST_CACHE_PS_0:
954 case SQ_ALU_CONST_CACHE_PS_1:
955 case SQ_ALU_CONST_CACHE_PS_2:
956 case SQ_ALU_CONST_CACHE_PS_3:
957 case SQ_ALU_CONST_CACHE_PS_4:
958 case SQ_ALU_CONST_CACHE_PS_5:
959 case SQ_ALU_CONST_CACHE_PS_6:
960 case SQ_ALU_CONST_CACHE_PS_7:
961 case SQ_ALU_CONST_CACHE_PS_8:
962 case SQ_ALU_CONST_CACHE_PS_9:
963 case SQ_ALU_CONST_CACHE_PS_10:
964 case SQ_ALU_CONST_CACHE_PS_11:
965 case SQ_ALU_CONST_CACHE_PS_12:
966 case SQ_ALU_CONST_CACHE_PS_13:
967 case SQ_ALU_CONST_CACHE_PS_14:
968 case SQ_ALU_CONST_CACHE_PS_15:
969 case SQ_ALU_CONST_CACHE_VS_0:
970 case SQ_ALU_CONST_CACHE_VS_1:
971 case SQ_ALU_CONST_CACHE_VS_2:
972 case SQ_ALU_CONST_CACHE_VS_3:
973 case SQ_ALU_CONST_CACHE_VS_4:
974 case SQ_ALU_CONST_CACHE_VS_5:
975 case SQ_ALU_CONST_CACHE_VS_6:
976 case SQ_ALU_CONST_CACHE_VS_7:
977 case SQ_ALU_CONST_CACHE_VS_8:
978 case SQ_ALU_CONST_CACHE_VS_9:
979 case SQ_ALU_CONST_CACHE_VS_10:
980 case SQ_ALU_CONST_CACHE_VS_11:
981 case SQ_ALU_CONST_CACHE_VS_12:
982 case SQ_ALU_CONST_CACHE_VS_13:
983 case SQ_ALU_CONST_CACHE_VS_14:
984 case SQ_ALU_CONST_CACHE_VS_15:
985 case SQ_ALU_CONST_CACHE_HS_0:
986 case SQ_ALU_CONST_CACHE_HS_1:
987 case SQ_ALU_CONST_CACHE_HS_2:
988 case SQ_ALU_CONST_CACHE_HS_3:
989 case SQ_ALU_CONST_CACHE_HS_4:
990 case SQ_ALU_CONST_CACHE_HS_5:
991 case SQ_ALU_CONST_CACHE_HS_6:
992 case SQ_ALU_CONST_CACHE_HS_7:
993 case SQ_ALU_CONST_CACHE_HS_8:
994 case SQ_ALU_CONST_CACHE_HS_9:
995 case SQ_ALU_CONST_CACHE_HS_10:
996 case SQ_ALU_CONST_CACHE_HS_11:
997 case SQ_ALU_CONST_CACHE_HS_12:
998 case SQ_ALU_CONST_CACHE_HS_13:
999 case SQ_ALU_CONST_CACHE_HS_14:
1000 case SQ_ALU_CONST_CACHE_HS_15:
1001 case SQ_ALU_CONST_CACHE_LS_0:
1002 case SQ_ALU_CONST_CACHE_LS_1:
1003 case SQ_ALU_CONST_CACHE_LS_2:
1004 case SQ_ALU_CONST_CACHE_LS_3:
1005 case SQ_ALU_CONST_CACHE_LS_4:
1006 case SQ_ALU_CONST_CACHE_LS_5:
1007 case SQ_ALU_CONST_CACHE_LS_6:
1008 case SQ_ALU_CONST_CACHE_LS_7:
1009 case SQ_ALU_CONST_CACHE_LS_8:
1010 case SQ_ALU_CONST_CACHE_LS_9:
1011 case SQ_ALU_CONST_CACHE_LS_10:
1012 case SQ_ALU_CONST_CACHE_LS_11:
1013 case SQ_ALU_CONST_CACHE_LS_12:
1014 case SQ_ALU_CONST_CACHE_LS_13:
1015 case SQ_ALU_CONST_CACHE_LS_14:
1016 case SQ_ALU_CONST_CACHE_LS_15:
1017 r = evergreen_cs_packet_next_reloc(p, &reloc);
1018 if (r) {
1019 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1020 "0x%04X\n", reg);
1021 return -EINVAL;
1022 }
1023 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1024 break;
Alex Deucher033b5652011-06-08 15:26:45 -04001025 case SX_MEMORY_EXPORT_BASE:
1026 if (p->rdev->family >= CHIP_CAYMAN) {
1027 dev_warn(p->dev, "bad SET_CONFIG_REG "
1028 "0x%04X\n", reg);
1029 return -EINVAL;
1030 }
1031 r = evergreen_cs_packet_next_reloc(p, &reloc);
1032 if (r) {
1033 dev_warn(p->dev, "bad SET_CONFIG_REG "
1034 "0x%04X\n", reg);
1035 return -EINVAL;
1036 }
1037 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1038 break;
1039 case CAYMAN_SX_SCATTER_EXPORT_BASE:
1040 if (p->rdev->family < CHIP_CAYMAN) {
1041 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1042 "0x%04X\n", reg);
1043 return -EINVAL;
1044 }
1045 r = evergreen_cs_packet_next_reloc(p, &reloc);
1046 if (r) {
1047 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1048 "0x%04X\n", reg);
1049 return -EINVAL;
1050 }
1051 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1052 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001053 default:
1054 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1055 return -EINVAL;
1056 }
1057 return 0;
1058}
1059
1060/**
1061 * evergreen_check_texture_resource() - check if register is authorized or not
1062 * @p: parser structure holding parsing context
1063 * @idx: index into the cs buffer
1064 * @texture: texture's bo structure
1065 * @mipmap: mipmap's bo structure
1066 *
1067 * This function will check that the resource has valid field and that
1068 * the texture and mipmap bo object are big enough to cover this resource.
1069 */
Andi Kleen488479e2011-10-13 16:08:41 -07001070static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001071 struct radeon_bo *texture,
1072 struct radeon_bo *mipmap)
1073{
1074 /* XXX fill in */
1075 return 0;
1076}
1077
Marek Olšákdd220a02012-01-27 12:17:59 -05001078static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1079{
1080 u32 last_reg, m, i;
1081
1082 if (p->rdev->family >= CHIP_CAYMAN)
1083 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
1084 else
1085 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
1086
1087 i = (reg >> 7);
1088 if (i >= last_reg) {
1089 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1090 return false;
1091 }
1092 m = 1 << ((reg >> 2) & 31);
1093 if (p->rdev->family >= CHIP_CAYMAN) {
1094 if (!(cayman_reg_safe_bm[i] & m))
1095 return true;
1096 } else {
1097 if (!(evergreen_reg_safe_bm[i] & m))
1098 return true;
1099 }
1100 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1101 return false;
1102}
1103
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001104static int evergreen_packet3_check(struct radeon_cs_parser *p,
1105 struct radeon_cs_packet *pkt)
1106{
1107 struct radeon_cs_reloc *reloc;
1108 struct evergreen_cs_track *track;
1109 volatile u32 *ib;
1110 unsigned idx;
1111 unsigned i;
1112 unsigned start_reg, end_reg, reg;
1113 int r;
1114 u32 idx_value;
1115
1116 track = (struct evergreen_cs_track *)p->track;
1117 ib = p->ib->ptr;
1118 idx = pkt->idx + 1;
1119 idx_value = radeon_get_ib_value(p, idx);
1120
1121 switch (pkt->opcode) {
Dave Airlie2a19cac2011-02-28 16:11:48 +10001122 case PACKET3_SET_PREDICATION:
1123 {
1124 int pred_op;
1125 int tmp;
1126 if (pkt->count != 1) {
1127 DRM_ERROR("bad SET PREDICATION\n");
1128 return -EINVAL;
1129 }
1130
1131 tmp = radeon_get_ib_value(p, idx + 1);
1132 pred_op = (tmp >> 16) & 0x7;
1133
1134 /* for the clear predicate operation */
1135 if (pred_op == 0)
1136 return 0;
1137
1138 if (pred_op > 2) {
1139 DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
1140 return -EINVAL;
1141 }
1142
1143 r = evergreen_cs_packet_next_reloc(p, &reloc);
1144 if (r) {
1145 DRM_ERROR("bad SET PREDICATION\n");
1146 return -EINVAL;
1147 }
1148
1149 ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1150 ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
1151 }
1152 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001153 case PACKET3_CONTEXT_CONTROL:
1154 if (pkt->count != 1) {
1155 DRM_ERROR("bad CONTEXT_CONTROL\n");
1156 return -EINVAL;
1157 }
1158 break;
1159 case PACKET3_INDEX_TYPE:
1160 case PACKET3_NUM_INSTANCES:
1161 case PACKET3_CLEAR_STATE:
1162 if (pkt->count) {
1163 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
1164 return -EINVAL;
1165 }
1166 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001167 case CAYMAN_PACKET3_DEALLOC_STATE:
1168 if (p->rdev->family < CHIP_CAYMAN) {
1169 DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
1170 return -EINVAL;
1171 }
1172 if (pkt->count) {
1173 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
1174 return -EINVAL;
1175 }
1176 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001177 case PACKET3_INDEX_BASE:
1178 if (pkt->count != 1) {
1179 DRM_ERROR("bad INDEX_BASE\n");
1180 return -EINVAL;
1181 }
1182 r = evergreen_cs_packet_next_reloc(p, &reloc);
1183 if (r) {
1184 DRM_ERROR("bad INDEX_BASE\n");
1185 return -EINVAL;
1186 }
1187 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1188 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1189 r = evergreen_cs_track_check(p);
1190 if (r) {
1191 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1192 return r;
1193 }
1194 break;
1195 case PACKET3_DRAW_INDEX:
1196 if (pkt->count != 3) {
1197 DRM_ERROR("bad DRAW_INDEX\n");
1198 return -EINVAL;
1199 }
1200 r = evergreen_cs_packet_next_reloc(p, &reloc);
1201 if (r) {
1202 DRM_ERROR("bad DRAW_INDEX\n");
1203 return -EINVAL;
1204 }
1205 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1206 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1207 r = evergreen_cs_track_check(p);
1208 if (r) {
1209 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1210 return r;
1211 }
1212 break;
1213 case PACKET3_DRAW_INDEX_2:
1214 if (pkt->count != 4) {
1215 DRM_ERROR("bad DRAW_INDEX_2\n");
1216 return -EINVAL;
1217 }
1218 r = evergreen_cs_packet_next_reloc(p, &reloc);
1219 if (r) {
1220 DRM_ERROR("bad DRAW_INDEX_2\n");
1221 return -EINVAL;
1222 }
1223 ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1224 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1225 r = evergreen_cs_track_check(p);
1226 if (r) {
1227 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1228 return r;
1229 }
1230 break;
1231 case PACKET3_DRAW_INDEX_AUTO:
1232 if (pkt->count != 1) {
1233 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
1234 return -EINVAL;
1235 }
1236 r = evergreen_cs_track_check(p);
1237 if (r) {
1238 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1239 return r;
1240 }
1241 break;
1242 case PACKET3_DRAW_INDEX_MULTI_AUTO:
1243 if (pkt->count != 2) {
1244 DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
1245 return -EINVAL;
1246 }
1247 r = evergreen_cs_track_check(p);
1248 if (r) {
1249 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1250 return r;
1251 }
1252 break;
1253 case PACKET3_DRAW_INDEX_IMMD:
1254 if (pkt->count < 2) {
1255 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
1256 return -EINVAL;
1257 }
1258 r = evergreen_cs_track_check(p);
1259 if (r) {
1260 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1261 return r;
1262 }
1263 break;
1264 case PACKET3_DRAW_INDEX_OFFSET:
1265 if (pkt->count != 2) {
1266 DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
1267 return -EINVAL;
1268 }
1269 r = evergreen_cs_track_check(p);
1270 if (r) {
1271 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1272 return r;
1273 }
1274 break;
1275 case PACKET3_DRAW_INDEX_OFFSET_2:
1276 if (pkt->count != 3) {
1277 DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
1278 return -EINVAL;
1279 }
1280 r = evergreen_cs_track_check(p);
1281 if (r) {
1282 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1283 return r;
1284 }
1285 break;
Alex Deucher033b5652011-06-08 15:26:45 -04001286 case PACKET3_DISPATCH_DIRECT:
1287 if (pkt->count != 3) {
1288 DRM_ERROR("bad DISPATCH_DIRECT\n");
1289 return -EINVAL;
1290 }
1291 r = evergreen_cs_track_check(p);
1292 if (r) {
1293 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1294 return r;
1295 }
1296 break;
1297 case PACKET3_DISPATCH_INDIRECT:
1298 if (pkt->count != 1) {
1299 DRM_ERROR("bad DISPATCH_INDIRECT\n");
1300 return -EINVAL;
1301 }
1302 r = evergreen_cs_packet_next_reloc(p, &reloc);
1303 if (r) {
1304 DRM_ERROR("bad DISPATCH_INDIRECT\n");
1305 return -EINVAL;
1306 }
1307 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1308 r = evergreen_cs_track_check(p);
1309 if (r) {
1310 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1311 return r;
1312 }
1313 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001314 case PACKET3_WAIT_REG_MEM:
1315 if (pkt->count != 5) {
1316 DRM_ERROR("bad WAIT_REG_MEM\n");
1317 return -EINVAL;
1318 }
1319 /* bit 4 is reg (0) or mem (1) */
1320 if (idx_value & 0x10) {
1321 r = evergreen_cs_packet_next_reloc(p, &reloc);
1322 if (r) {
1323 DRM_ERROR("bad WAIT_REG_MEM\n");
1324 return -EINVAL;
1325 }
1326 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1327 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1328 }
1329 break;
1330 case PACKET3_SURFACE_SYNC:
1331 if (pkt->count != 3) {
1332 DRM_ERROR("bad SURFACE_SYNC\n");
1333 return -EINVAL;
1334 }
1335 /* 0xffffffff/0x0 is flush all cache flag */
1336 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
1337 radeon_get_ib_value(p, idx + 2) != 0) {
1338 r = evergreen_cs_packet_next_reloc(p, &reloc);
1339 if (r) {
1340 DRM_ERROR("bad SURFACE_SYNC\n");
1341 return -EINVAL;
1342 }
1343 ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1344 }
1345 break;
1346 case PACKET3_EVENT_WRITE:
1347 if (pkt->count != 2 && pkt->count != 0) {
1348 DRM_ERROR("bad EVENT_WRITE\n");
1349 return -EINVAL;
1350 }
1351 if (pkt->count) {
1352 r = evergreen_cs_packet_next_reloc(p, &reloc);
1353 if (r) {
1354 DRM_ERROR("bad EVENT_WRITE\n");
1355 return -EINVAL;
1356 }
1357 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1358 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1359 }
1360 break;
1361 case PACKET3_EVENT_WRITE_EOP:
1362 if (pkt->count != 4) {
1363 DRM_ERROR("bad EVENT_WRITE_EOP\n");
1364 return -EINVAL;
1365 }
1366 r = evergreen_cs_packet_next_reloc(p, &reloc);
1367 if (r) {
1368 DRM_ERROR("bad EVENT_WRITE_EOP\n");
1369 return -EINVAL;
1370 }
1371 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1372 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1373 break;
1374 case PACKET3_EVENT_WRITE_EOS:
1375 if (pkt->count != 3) {
1376 DRM_ERROR("bad EVENT_WRITE_EOS\n");
1377 return -EINVAL;
1378 }
1379 r = evergreen_cs_packet_next_reloc(p, &reloc);
1380 if (r) {
1381 DRM_ERROR("bad EVENT_WRITE_EOS\n");
1382 return -EINVAL;
1383 }
1384 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1385 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1386 break;
1387 case PACKET3_SET_CONFIG_REG:
1388 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
1389 end_reg = 4 * pkt->count + start_reg - 4;
1390 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
1391 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
1392 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
1393 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
1394 return -EINVAL;
1395 }
1396 for (i = 0; i < pkt->count; i++) {
1397 reg = start_reg + (4 * i);
1398 r = evergreen_cs_check_reg(p, reg, idx+1+i);
1399 if (r)
1400 return r;
1401 }
1402 break;
1403 case PACKET3_SET_CONTEXT_REG:
1404 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
1405 end_reg = 4 * pkt->count + start_reg - 4;
1406 if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
1407 (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
1408 (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
1409 DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
1410 return -EINVAL;
1411 }
1412 for (i = 0; i < pkt->count; i++) {
1413 reg = start_reg + (4 * i);
1414 r = evergreen_cs_check_reg(p, reg, idx+1+i);
1415 if (r)
1416 return r;
1417 }
1418 break;
1419 case PACKET3_SET_RESOURCE:
1420 if (pkt->count % 8) {
1421 DRM_ERROR("bad SET_RESOURCE\n");
1422 return -EINVAL;
1423 }
1424 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
1425 end_reg = 4 * pkt->count + start_reg - 4;
1426 if ((start_reg < PACKET3_SET_RESOURCE_START) ||
1427 (start_reg >= PACKET3_SET_RESOURCE_END) ||
1428 (end_reg >= PACKET3_SET_RESOURCE_END)) {
1429 DRM_ERROR("bad SET_RESOURCE\n");
1430 return -EINVAL;
1431 }
1432 for (i = 0; i < (pkt->count / 8); i++) {
1433 struct radeon_bo *texture, *mipmap;
1434 u32 size, offset;
1435
1436 switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
1437 case SQ_TEX_VTX_VALID_TEXTURE:
1438 /* tex base */
1439 r = evergreen_cs_packet_next_reloc(p, &reloc);
1440 if (r) {
1441 DRM_ERROR("bad SET_RESOURCE (tex)\n");
1442 return -EINVAL;
1443 }
Alex Deucher09d7e782010-06-23 18:27:11 -04001444 ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Jerome Glisse721604a2012-01-05 22:11:05 -05001445 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Alex Deucherf3a71df2011-11-28 14:49:28 -05001446 ib[idx+1+(i*8)+1] |=
1447 TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1448 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1449 ib[idx+1+(i*8)+6] |=
1450 TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
1451 ib[idx+1+(i*8)+7] |=
1452 TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
1453 }
Marek Olšáke70f2242011-10-25 01:38:45 +02001454 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001455 texture = reloc->robj;
1456 /* tex mip base */
1457 r = evergreen_cs_packet_next_reloc(p, &reloc);
1458 if (r) {
1459 DRM_ERROR("bad SET_RESOURCE (tex)\n");
1460 return -EINVAL;
1461 }
Alex Deucher09d7e782010-06-23 18:27:11 -04001462 ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001463 mipmap = reloc->robj;
1464 r = evergreen_check_texture_resource(p, idx+1+(i*8),
1465 texture, mipmap);
1466 if (r)
1467 return r;
1468 break;
1469 case SQ_TEX_VTX_VALID_BUFFER:
1470 /* vtx base */
1471 r = evergreen_cs_packet_next_reloc(p, &reloc);
1472 if (r) {
1473 DRM_ERROR("bad SET_RESOURCE (vtx)\n");
1474 return -EINVAL;
1475 }
1476 offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
1477 size = radeon_get_ib_value(p, idx+1+(i*8)+1);
1478 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
1479 /* force size to size of the buffer */
1480 dev_warn(p->dev, "vbo resource seems too big for the bo\n");
1481 ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
1482 }
1483 ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
1484 ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1485 break;
1486 case SQ_TEX_VTX_INVALID_TEXTURE:
1487 case SQ_TEX_VTX_INVALID_BUFFER:
1488 default:
1489 DRM_ERROR("bad SET_RESOURCE\n");
1490 return -EINVAL;
1491 }
1492 }
1493 break;
1494 case PACKET3_SET_ALU_CONST:
1495 /* XXX fix me ALU const buffers only */
1496 break;
1497 case PACKET3_SET_BOOL_CONST:
1498 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
1499 end_reg = 4 * pkt->count + start_reg - 4;
1500 if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
1501 (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
1502 (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
1503 DRM_ERROR("bad SET_BOOL_CONST\n");
1504 return -EINVAL;
1505 }
1506 break;
1507 case PACKET3_SET_LOOP_CONST:
1508 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
1509 end_reg = 4 * pkt->count + start_reg - 4;
1510 if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
1511 (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
1512 (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
1513 DRM_ERROR("bad SET_LOOP_CONST\n");
1514 return -EINVAL;
1515 }
1516 break;
1517 case PACKET3_SET_CTL_CONST:
1518 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
1519 end_reg = 4 * pkt->count + start_reg - 4;
1520 if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
1521 (start_reg >= PACKET3_SET_CTL_CONST_END) ||
1522 (end_reg >= PACKET3_SET_CTL_CONST_END)) {
1523 DRM_ERROR("bad SET_CTL_CONST\n");
1524 return -EINVAL;
1525 }
1526 break;
1527 case PACKET3_SET_SAMPLER:
1528 if (pkt->count % 3) {
1529 DRM_ERROR("bad SET_SAMPLER\n");
1530 return -EINVAL;
1531 }
1532 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
1533 end_reg = 4 * pkt->count + start_reg - 4;
1534 if ((start_reg < PACKET3_SET_SAMPLER_START) ||
1535 (start_reg >= PACKET3_SET_SAMPLER_END) ||
1536 (end_reg >= PACKET3_SET_SAMPLER_END)) {
1537 DRM_ERROR("bad SET_SAMPLER\n");
1538 return -EINVAL;
1539 }
1540 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05001541 case PACKET3_STRMOUT_BUFFER_UPDATE:
1542 if (pkt->count != 4) {
1543 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
1544 return -EINVAL;
1545 }
1546 /* Updating memory at DST_ADDRESS. */
1547 if (idx_value & 0x1) {
1548 u64 offset;
1549 r = evergreen_cs_packet_next_reloc(p, &reloc);
1550 if (r) {
1551 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
1552 return -EINVAL;
1553 }
1554 offset = radeon_get_ib_value(p, idx+1);
1555 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
1556 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1557 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
1558 offset + 4, radeon_bo_size(reloc->robj));
1559 return -EINVAL;
1560 }
1561 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1562 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1563 }
1564 /* Reading data from SRC_ADDRESS. */
1565 if (((idx_value >> 1) & 0x3) == 2) {
1566 u64 offset;
1567 r = evergreen_cs_packet_next_reloc(p, &reloc);
1568 if (r) {
1569 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
1570 return -EINVAL;
1571 }
1572 offset = radeon_get_ib_value(p, idx+3);
1573 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
1574 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1575 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
1576 offset + 4, radeon_bo_size(reloc->robj));
1577 return -EINVAL;
1578 }
1579 ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1580 ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1581 }
1582 break;
1583 case PACKET3_COPY_DW:
1584 if (pkt->count != 4) {
1585 DRM_ERROR("bad COPY_DW (invalid count)\n");
1586 return -EINVAL;
1587 }
1588 if (idx_value & 0x1) {
1589 u64 offset;
1590 /* SRC is memory. */
1591 r = evergreen_cs_packet_next_reloc(p, &reloc);
1592 if (r) {
1593 DRM_ERROR("bad COPY_DW (missing src reloc)\n");
1594 return -EINVAL;
1595 }
1596 offset = radeon_get_ib_value(p, idx+1);
1597 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
1598 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1599 DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
1600 offset + 4, radeon_bo_size(reloc->robj));
1601 return -EINVAL;
1602 }
1603 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1604 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1605 } else {
1606 /* SRC is a reg. */
1607 reg = radeon_get_ib_value(p, idx+1) << 2;
1608 if (!evergreen_is_safe_reg(p, reg, idx+1))
1609 return -EINVAL;
1610 }
1611 if (idx_value & 0x2) {
1612 u64 offset;
1613 /* DST is memory. */
1614 r = evergreen_cs_packet_next_reloc(p, &reloc);
1615 if (r) {
1616 DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
1617 return -EINVAL;
1618 }
1619 offset = radeon_get_ib_value(p, idx+3);
1620 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
1621 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1622 DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
1623 offset + 4, radeon_bo_size(reloc->robj));
1624 return -EINVAL;
1625 }
1626 ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1627 ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1628 } else {
1629 /* DST is a reg. */
1630 reg = radeon_get_ib_value(p, idx+3) << 2;
1631 if (!evergreen_is_safe_reg(p, reg, idx+3))
1632 return -EINVAL;
1633 }
1634 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001635 case PACKET3_NOP:
1636 break;
1637 default:
1638 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
1639 return -EINVAL;
1640 }
1641 return 0;
1642}
1643
1644int evergreen_cs_parse(struct radeon_cs_parser *p)
1645{
1646 struct radeon_cs_packet pkt;
1647 struct evergreen_cs_track *track;
Alex Deucherf3a71df2011-11-28 14:49:28 -05001648 u32 tmp;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001649 int r;
1650
1651 if (p->track == NULL) {
1652 /* initialize tracker, we are in kms */
1653 track = kzalloc(sizeof(*track), GFP_KERNEL);
1654 if (track == NULL)
1655 return -ENOMEM;
1656 evergreen_cs_track_init(track);
Alex Deucherf3a71df2011-11-28 14:49:28 -05001657 if (p->rdev->family >= CHIP_CAYMAN)
1658 tmp = p->rdev->config.cayman.tile_config;
1659 else
1660 tmp = p->rdev->config.evergreen.tile_config;
1661
1662 switch (tmp & 0xf) {
1663 case 0:
1664 track->npipes = 1;
1665 break;
1666 case 1:
1667 default:
1668 track->npipes = 2;
1669 break;
1670 case 2:
1671 track->npipes = 4;
1672 break;
1673 case 3:
1674 track->npipes = 8;
1675 break;
1676 }
1677
1678 switch ((tmp & 0xf0) >> 4) {
1679 case 0:
1680 track->nbanks = 4;
1681 break;
1682 case 1:
1683 default:
1684 track->nbanks = 8;
1685 break;
1686 case 2:
1687 track->nbanks = 16;
1688 break;
1689 }
1690
1691 switch ((tmp & 0xf00) >> 8) {
1692 case 0:
1693 track->group_size = 256;
1694 break;
1695 case 1:
1696 default:
1697 track->group_size = 512;
1698 break;
1699 }
1700
1701 switch ((tmp & 0xf000) >> 12) {
1702 case 0:
1703 track->row_size = 1;
1704 break;
1705 case 1:
1706 default:
1707 track->row_size = 2;
1708 break;
1709 case 2:
1710 track->row_size = 4;
1711 break;
1712 }
1713
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001714 p->track = track;
1715 }
1716 do {
1717 r = evergreen_cs_packet_parse(p, &pkt, p->idx);
1718 if (r) {
1719 kfree(p->track);
1720 p->track = NULL;
1721 return r;
1722 }
1723 p->idx += pkt.count + 2;
1724 switch (pkt.type) {
1725 case PACKET_TYPE0:
1726 r = evergreen_cs_parse_packet0(p, &pkt);
1727 break;
1728 case PACKET_TYPE2:
1729 break;
1730 case PACKET_TYPE3:
1731 r = evergreen_packet3_check(p, &pkt);
1732 break;
1733 default:
1734 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
1735 kfree(p->track);
1736 p->track = NULL;
1737 return -EINVAL;
1738 }
1739 if (r) {
1740 kfree(p->track);
1741 p->track = NULL;
1742 return r;
1743 }
1744 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
1745#if 0
1746 for (r = 0; r < p->ib->length_dw; r++) {
1747 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
1748 mdelay(1);
1749 }
1750#endif
1751 kfree(p->track);
1752 p->track = NULL;
1753 return 0;
1754}
1755
Jerome Glisse721604a2012-01-05 22:11:05 -05001756/* vm parser */
1757static bool evergreen_vm_reg_valid(u32 reg)
1758{
1759 /* context regs are fine */
1760 if (reg >= 0x28000)
1761 return true;
1762
1763 /* check config regs */
1764 switch (reg) {
1765 case GRBM_GFX_INDEX:
1766 case VGT_VTX_VECT_EJECT_REG:
1767 case VGT_CACHE_INVALIDATION:
1768 case VGT_GS_VERTEX_REUSE:
1769 case VGT_PRIMITIVE_TYPE:
1770 case VGT_INDEX_TYPE:
1771 case VGT_NUM_INDICES:
1772 case VGT_NUM_INSTANCES:
1773 case VGT_COMPUTE_DIM_X:
1774 case VGT_COMPUTE_DIM_Y:
1775 case VGT_COMPUTE_DIM_Z:
1776 case VGT_COMPUTE_START_X:
1777 case VGT_COMPUTE_START_Y:
1778 case VGT_COMPUTE_START_Z:
1779 case VGT_COMPUTE_INDEX:
1780 case VGT_COMPUTE_THREAD_GROUP_SIZE:
1781 case VGT_HS_OFFCHIP_PARAM:
1782 case PA_CL_ENHANCE:
1783 case PA_SU_LINE_STIPPLE_VALUE:
1784 case PA_SC_LINE_STIPPLE_STATE:
1785 case PA_SC_ENHANCE:
1786 case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ:
1787 case SQ_DYN_GPR_SIMD_LOCK_EN:
1788 case SQ_CONFIG:
1789 case SQ_GPR_RESOURCE_MGMT_1:
1790 case SQ_GLOBAL_GPR_RESOURCE_MGMT_1:
1791 case SQ_GLOBAL_GPR_RESOURCE_MGMT_2:
1792 case SQ_CONST_MEM_BASE:
1793 case SQ_STATIC_THREAD_MGMT_1:
1794 case SQ_STATIC_THREAD_MGMT_2:
1795 case SQ_STATIC_THREAD_MGMT_3:
1796 case SPI_CONFIG_CNTL:
1797 case SPI_CONFIG_CNTL_1:
1798 case TA_CNTL_AUX:
1799 case DB_DEBUG:
1800 case DB_DEBUG2:
1801 case DB_DEBUG3:
1802 case DB_DEBUG4:
1803 case DB_WATERMARKS:
1804 case TD_PS_BORDER_COLOR_INDEX:
1805 case TD_PS_BORDER_COLOR_RED:
1806 case TD_PS_BORDER_COLOR_GREEN:
1807 case TD_PS_BORDER_COLOR_BLUE:
1808 case TD_PS_BORDER_COLOR_ALPHA:
1809 case TD_VS_BORDER_COLOR_INDEX:
1810 case TD_VS_BORDER_COLOR_RED:
1811 case TD_VS_BORDER_COLOR_GREEN:
1812 case TD_VS_BORDER_COLOR_BLUE:
1813 case TD_VS_BORDER_COLOR_ALPHA:
1814 case TD_GS_BORDER_COLOR_INDEX:
1815 case TD_GS_BORDER_COLOR_RED:
1816 case TD_GS_BORDER_COLOR_GREEN:
1817 case TD_GS_BORDER_COLOR_BLUE:
1818 case TD_GS_BORDER_COLOR_ALPHA:
1819 case TD_HS_BORDER_COLOR_INDEX:
1820 case TD_HS_BORDER_COLOR_RED:
1821 case TD_HS_BORDER_COLOR_GREEN:
1822 case TD_HS_BORDER_COLOR_BLUE:
1823 case TD_HS_BORDER_COLOR_ALPHA:
1824 case TD_LS_BORDER_COLOR_INDEX:
1825 case TD_LS_BORDER_COLOR_RED:
1826 case TD_LS_BORDER_COLOR_GREEN:
1827 case TD_LS_BORDER_COLOR_BLUE:
1828 case TD_LS_BORDER_COLOR_ALPHA:
1829 case TD_CS_BORDER_COLOR_INDEX:
1830 case TD_CS_BORDER_COLOR_RED:
1831 case TD_CS_BORDER_COLOR_GREEN:
1832 case TD_CS_BORDER_COLOR_BLUE:
1833 case TD_CS_BORDER_COLOR_ALPHA:
1834 case SQ_ESGS_RING_SIZE:
1835 case SQ_GSVS_RING_SIZE:
1836 case SQ_ESTMP_RING_SIZE:
1837 case SQ_GSTMP_RING_SIZE:
1838 case SQ_HSTMP_RING_SIZE:
1839 case SQ_LSTMP_RING_SIZE:
1840 case SQ_PSTMP_RING_SIZE:
1841 case SQ_VSTMP_RING_SIZE:
1842 case SQ_ESGS_RING_ITEMSIZE:
1843 case SQ_ESTMP_RING_ITEMSIZE:
1844 case SQ_GSTMP_RING_ITEMSIZE:
1845 case SQ_GSVS_RING_ITEMSIZE:
1846 case SQ_GS_VERT_ITEMSIZE:
1847 case SQ_GS_VERT_ITEMSIZE_1:
1848 case SQ_GS_VERT_ITEMSIZE_2:
1849 case SQ_GS_VERT_ITEMSIZE_3:
1850 case SQ_GSVS_RING_OFFSET_1:
1851 case SQ_GSVS_RING_OFFSET_2:
1852 case SQ_GSVS_RING_OFFSET_3:
1853 case SQ_HSTMP_RING_ITEMSIZE:
1854 case SQ_LSTMP_RING_ITEMSIZE:
1855 case SQ_PSTMP_RING_ITEMSIZE:
1856 case SQ_VSTMP_RING_ITEMSIZE:
1857 case VGT_TF_RING_SIZE:
1858 case SQ_ESGS_RING_BASE:
1859 case SQ_GSVS_RING_BASE:
1860 case SQ_ESTMP_RING_BASE:
1861 case SQ_GSTMP_RING_BASE:
1862 case SQ_HSTMP_RING_BASE:
1863 case SQ_LSTMP_RING_BASE:
1864 case SQ_PSTMP_RING_BASE:
1865 case SQ_VSTMP_RING_BASE:
1866 case CAYMAN_VGT_OFFCHIP_LDS_BASE:
1867 case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
1868 return true;
1869 default:
1870 return false;
1871 }
1872}
1873
1874static int evergreen_vm_packet3_check(struct radeon_device *rdev,
1875 u32 *ib, struct radeon_cs_packet *pkt)
1876{
1877 u32 idx = pkt->idx + 1;
1878 u32 idx_value = ib[idx];
1879 u32 start_reg, end_reg, reg, i;
1880
1881 switch (pkt->opcode) {
1882 case PACKET3_NOP:
1883 case PACKET3_SET_BASE:
1884 case PACKET3_CLEAR_STATE:
1885 case PACKET3_INDEX_BUFFER_SIZE:
1886 case PACKET3_DISPATCH_DIRECT:
1887 case PACKET3_DISPATCH_INDIRECT:
1888 case PACKET3_MODE_CONTROL:
1889 case PACKET3_SET_PREDICATION:
1890 case PACKET3_COND_EXEC:
1891 case PACKET3_PRED_EXEC:
1892 case PACKET3_DRAW_INDIRECT:
1893 case PACKET3_DRAW_INDEX_INDIRECT:
1894 case PACKET3_INDEX_BASE:
1895 case PACKET3_DRAW_INDEX_2:
1896 case PACKET3_CONTEXT_CONTROL:
1897 case PACKET3_DRAW_INDEX_OFFSET:
1898 case PACKET3_INDEX_TYPE:
1899 case PACKET3_DRAW_INDEX:
1900 case PACKET3_DRAW_INDEX_AUTO:
1901 case PACKET3_DRAW_INDEX_IMMD:
1902 case PACKET3_NUM_INSTANCES:
1903 case PACKET3_DRAW_INDEX_MULTI_AUTO:
1904 case PACKET3_STRMOUT_BUFFER_UPDATE:
1905 case PACKET3_DRAW_INDEX_OFFSET_2:
1906 case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
1907 case PACKET3_MPEG_INDEX:
1908 case PACKET3_WAIT_REG_MEM:
1909 case PACKET3_MEM_WRITE:
1910 case PACKET3_SURFACE_SYNC:
1911 case PACKET3_EVENT_WRITE:
1912 case PACKET3_EVENT_WRITE_EOP:
1913 case PACKET3_EVENT_WRITE_EOS:
1914 case PACKET3_SET_CONTEXT_REG:
1915 case PACKET3_SET_BOOL_CONST:
1916 case PACKET3_SET_LOOP_CONST:
1917 case PACKET3_SET_RESOURCE:
1918 case PACKET3_SET_SAMPLER:
1919 case PACKET3_SET_CTL_CONST:
1920 case PACKET3_SET_RESOURCE_OFFSET:
1921 case PACKET3_SET_CONTEXT_REG_INDIRECT:
1922 case PACKET3_SET_RESOURCE_INDIRECT:
1923 case CAYMAN_PACKET3_DEALLOC_STATE:
1924 break;
1925 case PACKET3_COND_WRITE:
1926 if (idx_value & 0x100) {
1927 reg = ib[idx + 5] * 4;
1928 if (!evergreen_vm_reg_valid(reg))
1929 return -EINVAL;
1930 }
1931 break;
1932 case PACKET3_COPY_DW:
1933 if (idx_value & 0x2) {
1934 reg = ib[idx + 3] * 4;
1935 if (!evergreen_vm_reg_valid(reg))
1936 return -EINVAL;
1937 }
1938 break;
1939 case PACKET3_SET_CONFIG_REG:
1940 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
1941 end_reg = 4 * pkt->count + start_reg - 4;
1942 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
1943 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
1944 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
1945 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
1946 return -EINVAL;
1947 }
1948 for (i = 0; i < pkt->count; i++) {
1949 reg = start_reg + (4 * i);
1950 if (!evergreen_vm_reg_valid(reg))
1951 return -EINVAL;
1952 }
1953 break;
1954 default:
1955 return -EINVAL;
1956 }
1957 return 0;
1958}
1959
1960int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
1961{
1962 int ret = 0;
1963 u32 idx = 0;
1964 struct radeon_cs_packet pkt;
1965
1966 do {
1967 pkt.idx = idx;
1968 pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
1969 pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
1970 pkt.one_reg_wr = 0;
1971 switch (pkt.type) {
1972 case PACKET_TYPE0:
1973 dev_err(rdev->dev, "Packet0 not allowed!\n");
1974 ret = -EINVAL;
1975 break;
1976 case PACKET_TYPE2:
Alex Deucher0b41da62012-01-12 15:42:37 -05001977 idx += 1;
Jerome Glisse721604a2012-01-05 22:11:05 -05001978 break;
1979 case PACKET_TYPE3:
1980 pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
1981 ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
Alex Deucher0b41da62012-01-12 15:42:37 -05001982 idx += pkt.count + 2;
Jerome Glisse721604a2012-01-05 22:11:05 -05001983 break;
1984 default:
1985 dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
1986 ret = -EINVAL;
1987 break;
1988 }
1989 if (ret)
1990 break;
Jerome Glisse721604a2012-01-05 22:11:05 -05001991 } while (idx < ib->length_dw);
1992
1993 return ret;
1994}