via_verifier.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. /*
  2. * Copyright 2004 The Unichrome Project. All Rights Reserved.
  3. * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the
  13. * next paragraph) shall be included in all copies or substantial portions
  14. * 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 NON-INFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(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 OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. *
  24. * Author: Thomas Hellstrom 2004, 2005.
  25. * This code was written using docs obtained under NDA from VIA Inc.
  26. *
  27. * Don't run this code directly on an AGP buffer. Due to cache problems it will
  28. * be very slow.
  29. */
  30. #include "via_3d_reg.h"
  31. #include "drmP.h"
  32. #include "drm.h"
  33. #include "via_drm.h"
  34. #include "via_verifier.h"
  35. #include "via_drv.h"
  36. typedef enum {
  37. state_command,
  38. state_header2,
  39. state_header1,
  40. state_vheader5,
  41. state_vheader6,
  42. state_error
  43. } verifier_state_t;
  44. typedef enum {
  45. no_check = 0,
  46. check_for_header2,
  47. check_for_header1,
  48. check_for_header2_err,
  49. check_for_header1_err,
  50. check_for_fire,
  51. check_z_buffer_addr0,
  52. check_z_buffer_addr1,
  53. check_z_buffer_addr_mode,
  54. check_destination_addr0,
  55. check_destination_addr1,
  56. check_destination_addr_mode,
  57. check_for_dummy,
  58. check_for_dd,
  59. check_texture_addr0,
  60. check_texture_addr1,
  61. check_texture_addr2,
  62. check_texture_addr3,
  63. check_texture_addr4,
  64. check_texture_addr5,
  65. check_texture_addr6,
  66. check_texture_addr7,
  67. check_texture_addr8,
  68. check_texture_addr_mode,
  69. check_for_vertex_count,
  70. check_number_texunits,
  71. forbidden_command
  72. } hazard_t;
  73. /*
  74. * Associates each hazard above with a possible multi-command
  75. * sequence. For example an address that is split over multiple
  76. * commands and that needs to be checked at the first command
  77. * that does not include any part of the address.
  78. */
  79. static drm_via_sequence_t seqs[] = {
  80. no_sequence,
  81. no_sequence,
  82. no_sequence,
  83. no_sequence,
  84. no_sequence,
  85. no_sequence,
  86. z_address,
  87. z_address,
  88. z_address,
  89. dest_address,
  90. dest_address,
  91. dest_address,
  92. no_sequence,
  93. no_sequence,
  94. tex_address,
  95. tex_address,
  96. tex_address,
  97. tex_address,
  98. tex_address,
  99. tex_address,
  100. tex_address,
  101. tex_address,
  102. tex_address,
  103. tex_address,
  104. no_sequence
  105. };
  106. typedef struct {
  107. unsigned int code;
  108. hazard_t hz;
  109. } hz_init_t;
  110. static hz_init_t init_table1[] = {
  111. {0xf2, check_for_header2_err},
  112. {0xf0, check_for_header1_err},
  113. {0xee, check_for_fire},
  114. {0xcc, check_for_dummy},
  115. {0xdd, check_for_dd},
  116. {0x00, no_check},
  117. {0x10, check_z_buffer_addr0},
  118. {0x11, check_z_buffer_addr1},
  119. {0x12, check_z_buffer_addr_mode},
  120. {0x13, no_check},
  121. {0x14, no_check},
  122. {0x15, no_check},
  123. {0x23, no_check},
  124. {0x24, no_check},
  125. {0x33, no_check},
  126. {0x34, no_check},
  127. {0x35, no_check},
  128. {0x36, no_check},
  129. {0x37, no_check},
  130. {0x38, no_check},
  131. {0x39, no_check},
  132. {0x3A, no_check},
  133. {0x3B, no_check},
  134. {0x3C, no_check},
  135. {0x3D, no_check},
  136. {0x3E, no_check},
  137. {0x40, check_destination_addr0},
  138. {0x41, check_destination_addr1},
  139. {0x42, check_destination_addr_mode},
  140. {0x43, no_check},
  141. {0x44, no_check},
  142. {0x50, no_check},
  143. {0x51, no_check},
  144. {0x52, no_check},
  145. {0x53, no_check},
  146. {0x54, no_check},
  147. {0x55, no_check},
  148. {0x56, no_check},
  149. {0x57, no_check},
  150. {0x58, no_check},
  151. {0x70, no_check},
  152. {0x71, no_check},
  153. {0x78, no_check},
  154. {0x79, no_check},
  155. {0x7A, no_check},
  156. {0x7B, no_check},
  157. {0x7C, no_check},
  158. {0x7D, check_for_vertex_count}
  159. };
  160. static hz_init_t init_table2[] = {
  161. {0xf2, check_for_header2_err},
  162. {0xf0, check_for_header1_err},
  163. {0xee, check_for_fire},
  164. {0xcc, check_for_dummy},
  165. {0x00, check_texture_addr0},
  166. {0x01, check_texture_addr0},
  167. {0x02, check_texture_addr0},
  168. {0x03, check_texture_addr0},
  169. {0x04, check_texture_addr0},
  170. {0x05, check_texture_addr0},
  171. {0x06, check_texture_addr0},
  172. {0x07, check_texture_addr0},
  173. {0x08, check_texture_addr0},
  174. {0x09, check_texture_addr0},
  175. {0x20, check_texture_addr1},
  176. {0x21, check_texture_addr1},
  177. {0x22, check_texture_addr1},
  178. {0x23, check_texture_addr4},
  179. {0x2B, check_texture_addr3},
  180. {0x2C, check_texture_addr3},
  181. {0x2D, check_texture_addr3},
  182. {0x2E, check_texture_addr3},
  183. {0x2F, check_texture_addr3},
  184. {0x30, check_texture_addr3},
  185. {0x31, check_texture_addr3},
  186. {0x32, check_texture_addr3},
  187. {0x33, check_texture_addr3},
  188. {0x34, check_texture_addr3},
  189. {0x4B, check_texture_addr5},
  190. {0x4C, check_texture_addr6},
  191. {0x51, check_texture_addr7},
  192. {0x52, check_texture_addr8},
  193. {0x77, check_texture_addr2},
  194. {0x78, no_check},
  195. {0x79, no_check},
  196. {0x7A, no_check},
  197. {0x7B, check_texture_addr_mode},
  198. {0x7C, no_check},
  199. {0x7D, no_check},
  200. {0x7E, no_check},
  201. {0x7F, no_check},
  202. {0x80, no_check},
  203. {0x81, no_check},
  204. {0x82, no_check},
  205. {0x83, no_check},
  206. {0x85, no_check},
  207. {0x86, no_check},
  208. {0x87, no_check},
  209. {0x88, no_check},
  210. {0x89, no_check},
  211. {0x8A, no_check},
  212. {0x90, no_check},
  213. {0x91, no_check},
  214. {0x92, no_check},
  215. {0x93, no_check}
  216. };
  217. static hz_init_t init_table3[] = {
  218. {0xf2, check_for_header2_err},
  219. {0xf0, check_for_header1_err},
  220. {0xcc, check_for_dummy},
  221. {0x00, check_number_texunits}
  222. };
  223. static hazard_t table1[256];
  224. static hazard_t table2[256];
  225. static hazard_t table3[256];
  226. static __inline__ int
  227. eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
  228. {
  229. if ((buf_end - *buf) >= num_words) {
  230. *buf += num_words;
  231. return 0;
  232. }
  233. DRM_ERROR("Illegal termination of DMA command buffer\n");
  234. return 1;
  235. }
  236. /*
  237. * Partially stolen from drm_memory.h
  238. */
  239. static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
  240. unsigned long offset,
  241. unsigned long size,
  242. drm_device_t * dev)
  243. {
  244. struct list_head *list;
  245. drm_map_list_t *r_list;
  246. drm_local_map_t *map = seq->map_cache;
  247. if (map && map->offset <= offset
  248. && (offset + size) <= (map->offset + map->size)) {
  249. return map;
  250. }
  251. list_for_each(list, &dev->maplist->head) {
  252. r_list = (drm_map_list_t *) list;
  253. map = r_list->map;
  254. if (!map)
  255. continue;
  256. if (map->offset <= offset
  257. && (offset + size) <= (map->offset + map->size)
  258. && !(map->flags & _DRM_RESTRICTED)
  259. && (map->type == _DRM_AGP)) {
  260. seq->map_cache = map;
  261. return map;
  262. }
  263. }
  264. return NULL;
  265. }
  266. /*
  267. * Require that all AGP texture levels reside in the same AGP map which should
  268. * be mappable by the client. This is not a big restriction.
  269. * FIXME: To actually enforce this security policy strictly, drm_rmmap
  270. * would have to wait for dma quiescent before removing an AGP map.
  271. * The via_drm_lookup_agp_map call in reality seems to take
  272. * very little CPU time.
  273. */
  274. static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
  275. {
  276. switch (cur_seq->unfinished) {
  277. case z_address:
  278. DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
  279. break;
  280. case dest_address:
  281. DRM_DEBUG("Destination start address is 0x%x\n",
  282. cur_seq->d_addr);
  283. break;
  284. case tex_address:
  285. if (cur_seq->agp_texture) {
  286. unsigned start =
  287. cur_seq->tex_level_lo[cur_seq->texture];
  288. unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
  289. unsigned long lo = ~0, hi = 0, tmp;
  290. uint32_t *addr, *pitch, *height, tex;
  291. unsigned i;
  292. if (end > 9)
  293. end = 9;
  294. if (start > 9)
  295. start = 9;
  296. addr =
  297. &(cur_seq->t_addr[tex = cur_seq->texture][start]);
  298. pitch = &(cur_seq->pitch[tex][start]);
  299. height = &(cur_seq->height[tex][start]);
  300. for (i = start; i <= end; ++i) {
  301. tmp = *addr++;
  302. if (tmp < lo)
  303. lo = tmp;
  304. tmp += (*height++ << *pitch++);
  305. if (tmp > hi)
  306. hi = tmp;
  307. }
  308. if (!via_drm_lookup_agp_map
  309. (cur_seq, lo, hi - lo, cur_seq->dev)) {
  310. DRM_ERROR
  311. ("AGP texture is not in allowed map\n");
  312. return 2;
  313. }
  314. }
  315. break;
  316. default:
  317. break;
  318. }
  319. cur_seq->unfinished = no_sequence;
  320. return 0;
  321. }
  322. static __inline__ int
  323. investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
  324. {
  325. register uint32_t tmp, *tmp_addr;
  326. if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
  327. int ret;
  328. if ((ret = finish_current_sequence(cur_seq)))
  329. return ret;
  330. }
  331. switch (hz) {
  332. case check_for_header2:
  333. if (cmd == HALCYON_HEADER2)
  334. return 1;
  335. return 0;
  336. case check_for_header1:
  337. if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
  338. return 1;
  339. return 0;
  340. case check_for_header2_err:
  341. if (cmd == HALCYON_HEADER2)
  342. return 1;
  343. DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
  344. break;
  345. case check_for_header1_err:
  346. if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
  347. return 1;
  348. DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
  349. break;
  350. case check_for_fire:
  351. if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
  352. return 1;
  353. DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
  354. break;
  355. case check_for_dummy:
  356. if (HC_DUMMY == cmd)
  357. return 0;
  358. DRM_ERROR("Illegal DMA HC_DUMMY command\n");
  359. break;
  360. case check_for_dd:
  361. if (0xdddddddd == cmd)
  362. return 0;
  363. DRM_ERROR("Illegal DMA 0xdddddddd command\n");
  364. break;
  365. case check_z_buffer_addr0:
  366. cur_seq->unfinished = z_address;
  367. cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
  368. (cmd & 0x00FFFFFF);
  369. return 0;
  370. case check_z_buffer_addr1:
  371. cur_seq->unfinished = z_address;
  372. cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
  373. ((cmd & 0xFF) << 24);
  374. return 0;
  375. case check_z_buffer_addr_mode:
  376. cur_seq->unfinished = z_address;
  377. if ((cmd & 0x0000C000) == 0)
  378. return 0;
  379. DRM_ERROR("Attempt to place Z buffer in system memory\n");
  380. return 2;
  381. case check_destination_addr0:
  382. cur_seq->unfinished = dest_address;
  383. cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
  384. (cmd & 0x00FFFFFF);
  385. return 0;
  386. case check_destination_addr1:
  387. cur_seq->unfinished = dest_address;
  388. cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
  389. ((cmd & 0xFF) << 24);
  390. return 0;
  391. case check_destination_addr_mode:
  392. cur_seq->unfinished = dest_address;
  393. if ((cmd & 0x0000C000) == 0)
  394. return 0;
  395. DRM_ERROR
  396. ("Attempt to place 3D drawing buffer in system memory\n");
  397. return 2;
  398. case check_texture_addr0:
  399. cur_seq->unfinished = tex_address;
  400. tmp = (cmd >> 24);
  401. tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
  402. *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
  403. return 0;
  404. case check_texture_addr1:
  405. cur_seq->unfinished = tex_address;
  406. tmp = ((cmd >> 24) - 0x20);
  407. tmp += tmp << 1;
  408. tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
  409. *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
  410. tmp_addr++;
  411. *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
  412. tmp_addr++;
  413. *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
  414. return 0;
  415. case check_texture_addr2:
  416. cur_seq->unfinished = tex_address;
  417. cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
  418. cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
  419. return 0;
  420. case check_texture_addr3:
  421. cur_seq->unfinished = tex_address;
  422. tmp = ((cmd >> 24) - 0x2B);
  423. cur_seq->pitch[cur_seq->texture][tmp] =
  424. (cmd & 0x00F00000) >> 20;
  425. if (!tmp && (cmd & 0x000FFFFF)) {
  426. DRM_ERROR
  427. ("Unimplemented texture level 0 pitch mode.\n");
  428. return 2;
  429. }
  430. return 0;
  431. case check_texture_addr4:
  432. cur_seq->unfinished = tex_address;
  433. tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
  434. *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
  435. return 0;
  436. case check_texture_addr5:
  437. case check_texture_addr6:
  438. cur_seq->unfinished = tex_address;
  439. /*
  440. * Texture width. We don't care since we have the pitch.
  441. */
  442. return 0;
  443. case check_texture_addr7:
  444. cur_seq->unfinished = tex_address;
  445. tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
  446. tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
  447. tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
  448. tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
  449. tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
  450. tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
  451. tmp_addr[0] = 1 << (cmd & 0x0000000F);
  452. return 0;
  453. case check_texture_addr8:
  454. cur_seq->unfinished = tex_address;
  455. tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
  456. tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
  457. tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
  458. tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
  459. tmp_addr[6] = 1 << (cmd & 0x0000000F);
  460. return 0;
  461. case check_texture_addr_mode:
  462. cur_seq->unfinished = tex_address;
  463. if (2 == (tmp = cmd & 0x00000003)) {
  464. DRM_ERROR
  465. ("Attempt to fetch texture from system memory.\n");
  466. return 2;
  467. }
  468. cur_seq->agp_texture = (tmp == 3);
  469. cur_seq->tex_palette_size[cur_seq->texture] =
  470. (cmd >> 16) & 0x000000007;
  471. return 0;
  472. case check_for_vertex_count:
  473. cur_seq->vertex_count = cmd & 0x0000FFFF;
  474. return 0;
  475. case check_number_texunits:
  476. cur_seq->multitex = (cmd >> 3) & 1;
  477. return 0;
  478. default:
  479. DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
  480. return 2;
  481. }
  482. return 2;
  483. }
  484. static __inline__ int
  485. via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
  486. drm_via_state_t * cur_seq)
  487. {
  488. drm_via_private_t *dev_priv =
  489. (drm_via_private_t *) cur_seq->dev->dev_private;
  490. uint32_t a_fire, bcmd, dw_count;
  491. int ret = 0;
  492. int have_fire;
  493. const uint32_t *buf = *buffer;
  494. while (buf < buf_end) {
  495. have_fire = 0;
  496. if ((buf_end - buf) < 2) {
  497. DRM_ERROR
  498. ("Unexpected termination of primitive list.\n");
  499. ret = 1;
  500. break;
  501. }
  502. if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
  503. break;
  504. bcmd = *buf++;
  505. if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
  506. DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
  507. *buf);
  508. ret = 1;
  509. break;
  510. }
  511. a_fire =
  512. *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
  513. HC_HE3Fire_MASK;
  514. /*
  515. * How many dwords per vertex ?
  516. */
  517. if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
  518. DRM_ERROR("Illegal B command vertex data for AGP.\n");
  519. ret = 1;
  520. break;
  521. }
  522. dw_count = 0;
  523. if (bcmd & (1 << 7))
  524. dw_count += (cur_seq->multitex) ? 2 : 1;
  525. if (bcmd & (1 << 8))
  526. dw_count += (cur_seq->multitex) ? 2 : 1;
  527. if (bcmd & (1 << 9))
  528. dw_count++;
  529. if (bcmd & (1 << 10))
  530. dw_count++;
  531. if (bcmd & (1 << 11))
  532. dw_count++;
  533. if (bcmd & (1 << 12))
  534. dw_count++;
  535. if (bcmd & (1 << 13))
  536. dw_count++;
  537. if (bcmd & (1 << 14))
  538. dw_count++;
  539. while (buf < buf_end) {
  540. if (*buf == a_fire) {
  541. if (dev_priv->num_fire_offsets >=
  542. VIA_FIRE_BUF_SIZE) {
  543. DRM_ERROR("Fire offset buffer full.\n");
  544. ret = 1;
  545. break;
  546. }
  547. dev_priv->fire_offsets[dev_priv->
  548. num_fire_offsets++] =
  549. buf;
  550. have_fire = 1;
  551. buf++;
  552. if (buf < buf_end && *buf == a_fire)
  553. buf++;
  554. break;
  555. }
  556. if ((*buf == HALCYON_HEADER2) ||
  557. ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
  558. DRM_ERROR("Missing Vertex Fire command, "
  559. "Stray Vertex Fire command or verifier "
  560. "lost sync.\n");
  561. ret = 1;
  562. break;
  563. }
  564. if ((ret = eat_words(&buf, buf_end, dw_count)))
  565. break;
  566. }
  567. if (buf >= buf_end && !have_fire) {
  568. DRM_ERROR("Missing Vertex Fire command or verifier "
  569. "lost sync.\n");
  570. ret = 1;
  571. break;
  572. }
  573. if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
  574. DRM_ERROR("AGP Primitive list end misaligned.\n");
  575. ret = 1;
  576. break;
  577. }
  578. }
  579. *buffer = buf;
  580. return ret;
  581. }
  582. static __inline__ verifier_state_t
  583. via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
  584. drm_via_state_t * hc_state)
  585. {
  586. uint32_t cmd;
  587. int hz_mode;
  588. hazard_t hz;
  589. const uint32_t *buf = *buffer;
  590. const hazard_t *hz_table;
  591. if ((buf_end - buf) < 2) {
  592. DRM_ERROR
  593. ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
  594. return state_error;
  595. }
  596. buf++;
  597. cmd = (*buf++ & 0xFFFF0000) >> 16;
  598. switch (cmd) {
  599. case HC_ParaType_CmdVdata:
  600. if (via_check_prim_list(&buf, buf_end, hc_state))
  601. return state_error;
  602. *buffer = buf;
  603. return state_command;
  604. case HC_ParaType_NotTex:
  605. hz_table = table1;
  606. break;
  607. case HC_ParaType_Tex:
  608. hc_state->texture = 0;
  609. hz_table = table2;
  610. break;
  611. case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
  612. hc_state->texture = 1;
  613. hz_table = table2;
  614. break;
  615. case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
  616. hz_table = table3;
  617. break;
  618. case HC_ParaType_Auto:
  619. if (eat_words(&buf, buf_end, 2))
  620. return state_error;
  621. *buffer = buf;
  622. return state_command;
  623. case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
  624. if (eat_words(&buf, buf_end, 32))
  625. return state_error;
  626. *buffer = buf;
  627. return state_command;
  628. case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
  629. case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
  630. DRM_ERROR("Texture palettes are rejected because of "
  631. "lack of info how to determine their size.\n");
  632. return state_error;
  633. case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
  634. DRM_ERROR("Fog factor palettes are rejected because of "
  635. "lack of info how to determine their size.\n");
  636. return state_error;
  637. default:
  638. /*
  639. * There are some unimplemented HC_ParaTypes here, that
  640. * need to be implemented if the Mesa driver is extended.
  641. */
  642. DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
  643. "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
  644. cmd, *(buf - 2));
  645. *buffer = buf;
  646. return state_error;
  647. }
  648. while (buf < buf_end) {
  649. cmd = *buf++;
  650. if ((hz = hz_table[cmd >> 24])) {
  651. if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
  652. if (hz_mode == 1) {
  653. buf--;
  654. break;
  655. }
  656. return state_error;
  657. }
  658. } else if (hc_state->unfinished &&
  659. finish_current_sequence(hc_state)) {
  660. return state_error;
  661. }
  662. }
  663. if (hc_state->unfinished && finish_current_sequence(hc_state)) {
  664. return state_error;
  665. }
  666. *buffer = buf;
  667. return state_command;
  668. }
  669. static __inline__ verifier_state_t
  670. via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
  671. const uint32_t * buf_end, int *fire_count)
  672. {
  673. uint32_t cmd;
  674. const uint32_t *buf = *buffer;
  675. const uint32_t *next_fire;
  676. int burst = 0;
  677. next_fire = dev_priv->fire_offsets[*fire_count];
  678. buf++;
  679. cmd = (*buf & 0xFFFF0000) >> 16;
  680. VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
  681. switch (cmd) {
  682. case HC_ParaType_CmdVdata:
  683. while ((buf < buf_end) &&
  684. (*fire_count < dev_priv->num_fire_offsets) &&
  685. (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
  686. while (buf <= next_fire) {
  687. VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
  688. (burst & 63), *buf++);
  689. burst += 4;
  690. }
  691. if ((buf < buf_end)
  692. && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
  693. buf++;
  694. if (++(*fire_count) < dev_priv->num_fire_offsets)
  695. next_fire = dev_priv->fire_offsets[*fire_count];
  696. }
  697. break;
  698. default:
  699. while (buf < buf_end) {
  700. if (*buf == HC_HEADER2 ||
  701. (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
  702. (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
  703. (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
  704. break;
  705. VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
  706. (burst & 63), *buf++);
  707. burst += 4;
  708. }
  709. }
  710. *buffer = buf;
  711. return state_command;
  712. }
  713. static __inline__ int verify_mmio_address(uint32_t address)
  714. {
  715. if ((address > 0x3FF) && (address < 0xC00)) {
  716. DRM_ERROR("Invalid VIDEO DMA command. "
  717. "Attempt to access 3D- or command burst area.\n");
  718. return 1;
  719. } else if ((address > 0xCFF) && (address < 0x1300)) {
  720. DRM_ERROR("Invalid VIDEO DMA command. "
  721. "Attempt to access PCI DMA area.\n");
  722. return 1;
  723. } else if (address > 0x13FF) {
  724. DRM_ERROR("Invalid VIDEO DMA command. "
  725. "Attempt to access VGA registers.\n");
  726. return 1;
  727. }
  728. return 0;
  729. }
  730. static __inline__ int
  731. verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
  732. uint32_t dwords)
  733. {
  734. const uint32_t *buf = *buffer;
  735. if (buf_end - buf < dwords) {
  736. DRM_ERROR("Illegal termination of video command.\n");
  737. return 1;
  738. }
  739. while (dwords--) {
  740. if (*buf++) {
  741. DRM_ERROR("Illegal video command tail.\n");
  742. return 1;
  743. }
  744. }
  745. *buffer = buf;
  746. return 0;
  747. }
  748. static __inline__ verifier_state_t
  749. via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
  750. {
  751. uint32_t cmd;
  752. const uint32_t *buf = *buffer;
  753. verifier_state_t ret = state_command;
  754. while (buf < buf_end) {
  755. cmd = *buf;
  756. if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
  757. (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
  758. if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
  759. break;
  760. DRM_ERROR("Invalid HALCYON_HEADER1 command. "
  761. "Attempt to access 3D- or command burst area.\n");
  762. ret = state_error;
  763. break;
  764. } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
  765. if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
  766. break;
  767. DRM_ERROR("Invalid HALCYON_HEADER1 command. "
  768. "Attempt to access VGA registers.\n");
  769. ret = state_error;
  770. break;
  771. } else {
  772. buf += 2;
  773. }
  774. }
  775. *buffer = buf;
  776. return ret;
  777. }
  778. static __inline__ verifier_state_t
  779. via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
  780. const uint32_t * buf_end)
  781. {
  782. register uint32_t cmd;
  783. const uint32_t *buf = *buffer;
  784. while (buf < buf_end) {
  785. cmd = *buf;
  786. if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
  787. break;
  788. VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
  789. buf++;
  790. }
  791. *buffer = buf;
  792. return state_command;
  793. }
  794. static __inline__ verifier_state_t
  795. via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
  796. {
  797. uint32_t data;
  798. const uint32_t *buf = *buffer;
  799. if (buf_end - buf < 4) {
  800. DRM_ERROR("Illegal termination of video header5 command\n");
  801. return state_error;
  802. }
  803. data = *buf++ & ~VIA_VIDEOMASK;
  804. if (verify_mmio_address(data))
  805. return state_error;
  806. data = *buf++;
  807. if (*buf++ != 0x00F50000) {
  808. DRM_ERROR("Illegal header5 header data\n");
  809. return state_error;
  810. }
  811. if (*buf++ != 0x00000000) {
  812. DRM_ERROR("Illegal header5 header data\n");
  813. return state_error;
  814. }
  815. if (eat_words(&buf, buf_end, data))
  816. return state_error;
  817. if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
  818. return state_error;
  819. *buffer = buf;
  820. return state_command;
  821. }
  822. static __inline__ verifier_state_t
  823. via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
  824. const uint32_t * buf_end)
  825. {
  826. uint32_t addr, count, i;
  827. const uint32_t *buf = *buffer;
  828. addr = *buf++ & ~VIA_VIDEOMASK;
  829. i = count = *buf;
  830. buf += 3;
  831. while (i--) {
  832. VIA_WRITE(addr, *buf++);
  833. }
  834. if (count & 3)
  835. buf += 4 - (count & 3);
  836. *buffer = buf;
  837. return state_command;
  838. }
  839. static __inline__ verifier_state_t
  840. via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
  841. {
  842. uint32_t data;
  843. const uint32_t *buf = *buffer;
  844. uint32_t i;
  845. if (buf_end - buf < 4) {
  846. DRM_ERROR("Illegal termination of video header6 command\n");
  847. return state_error;
  848. }
  849. buf++;
  850. data = *buf++;
  851. if (*buf++ != 0x00F60000) {
  852. DRM_ERROR("Illegal header6 header data\n");
  853. return state_error;
  854. }
  855. if (*buf++ != 0x00000000) {
  856. DRM_ERROR("Illegal header6 header data\n");
  857. return state_error;
  858. }
  859. if ((buf_end - buf) < (data << 1)) {
  860. DRM_ERROR("Illegal termination of video header6 command\n");
  861. return state_error;
  862. }
  863. for (i = 0; i < data; ++i) {
  864. if (verify_mmio_address(*buf++))
  865. return state_error;
  866. buf++;
  867. }
  868. data <<= 1;
  869. if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
  870. return state_error;
  871. *buffer = buf;
  872. return state_command;
  873. }
  874. static __inline__ verifier_state_t
  875. via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
  876. const uint32_t * buf_end)
  877. {
  878. uint32_t addr, count, i;
  879. const uint32_t *buf = *buffer;
  880. i = count = *++buf;
  881. buf += 3;
  882. while (i--) {
  883. addr = *buf++;
  884. VIA_WRITE(addr, *buf++);
  885. }
  886. count <<= 1;
  887. if (count & 3)
  888. buf += 4 - (count & 3);
  889. *buffer = buf;
  890. return state_command;
  891. }
  892. int
  893. via_verify_command_stream(const uint32_t * buf, unsigned int size,
  894. drm_device_t * dev, int agp)
  895. {
  896. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  897. drm_via_state_t *hc_state = &dev_priv->hc_state;
  898. drm_via_state_t saved_state = *hc_state;
  899. uint32_t cmd;
  900. const uint32_t *buf_end = buf + (size >> 2);
  901. verifier_state_t state = state_command;
  902. int pro_group_a = dev_priv->pro_group_a;
  903. hc_state->dev = dev;
  904. hc_state->unfinished = no_sequence;
  905. hc_state->map_cache = NULL;
  906. hc_state->agp = agp;
  907. hc_state->buf_start = buf;
  908. dev_priv->num_fire_offsets = 0;
  909. while (buf < buf_end) {
  910. switch (state) {
  911. case state_header2:
  912. state = via_check_header2(&buf, buf_end, hc_state);
  913. break;
  914. case state_header1:
  915. state = via_check_header1(&buf, buf_end);
  916. break;
  917. case state_vheader5:
  918. state = via_check_vheader5(&buf, buf_end);
  919. break;
  920. case state_vheader6:
  921. state = via_check_vheader6(&buf, buf_end);
  922. break;
  923. case state_command:
  924. if (HALCYON_HEADER2 == (cmd = *buf))
  925. state = state_header2;
  926. else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
  927. state = state_header1;
  928. else if (pro_group_a
  929. && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
  930. state = state_vheader5;
  931. else if (pro_group_a
  932. && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
  933. state = state_vheader6;
  934. else {
  935. DRM_ERROR
  936. ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
  937. cmd);
  938. state = state_error;
  939. }
  940. break;
  941. case state_error:
  942. default:
  943. *hc_state = saved_state;
  944. return DRM_ERR(EINVAL);
  945. }
  946. }
  947. if (state == state_error) {
  948. *hc_state = saved_state;
  949. return DRM_ERR(EINVAL);
  950. }
  951. return 0;
  952. }
  953. int
  954. via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
  955. unsigned int size)
  956. {
  957. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  958. uint32_t cmd;
  959. const uint32_t *buf_end = buf + (size >> 2);
  960. verifier_state_t state = state_command;
  961. int fire_count = 0;
  962. while (buf < buf_end) {
  963. switch (state) {
  964. case state_header2:
  965. state =
  966. via_parse_header2(dev_priv, &buf, buf_end,
  967. &fire_count);
  968. break;
  969. case state_header1:
  970. state = via_parse_header1(dev_priv, &buf, buf_end);
  971. break;
  972. case state_vheader5:
  973. state = via_parse_vheader5(dev_priv, &buf, buf_end);
  974. break;
  975. case state_vheader6:
  976. state = via_parse_vheader6(dev_priv, &buf, buf_end);
  977. break;
  978. case state_command:
  979. if (HALCYON_HEADER2 == (cmd = *buf))
  980. state = state_header2;
  981. else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
  982. state = state_header1;
  983. else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
  984. state = state_vheader5;
  985. else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
  986. state = state_vheader6;
  987. else {
  988. DRM_ERROR
  989. ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
  990. cmd);
  991. state = state_error;
  992. }
  993. break;
  994. case state_error:
  995. default:
  996. return DRM_ERR(EINVAL);
  997. }
  998. }
  999. if (state == state_error) {
  1000. return DRM_ERR(EINVAL);
  1001. }
  1002. return 0;
  1003. }
  1004. static void
  1005. setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
  1006. {
  1007. int i;
  1008. for (i = 0; i < 256; ++i) {
  1009. table[i] = forbidden_command;
  1010. }
  1011. for (i = 0; i < size; ++i) {
  1012. table[init_table[i].code] = init_table[i].hz;
  1013. }
  1014. }
  1015. void via_init_command_verifier(void)
  1016. {
  1017. setup_hazard_table(init_table1, table1,
  1018. sizeof(init_table1) / sizeof(hz_init_t));
  1019. setup_hazard_table(init_table2, table2,
  1020. sizeof(init_table2) / sizeof(hz_init_t));
  1021. setup_hazard_table(init_table3, table3,
  1022. sizeof(init_table3) / sizeof(hz_init_t));
  1023. }