via_verifier.c 28 KB

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