qxl.c 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365
  1. /*
  2. * Copyright (C) 2010 Red Hat, Inc.
  3. *
  4. * written by Yaniv Kamay, Izik Eidus, Gerd Hoffmann
  5. * maintained by Gerd Hoffmann <kraxel@redhat.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <zlib.h>
  21. #include <stdint.h>
  22. #include "qemu-common.h"
  23. #include "qemu/timer.h"
  24. #include "qemu/queue.h"
  25. #include "qemu/atomic.h"
  26. #include "monitor/monitor.h"
  27. #include "sysemu/sysemu.h"
  28. #include "trace.h"
  29. #include "qxl.h"
  30. /*
  31. * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
  32. * such can be changed by the guest, so to avoid a guest trigerrable
  33. * abort we just qxl_set_guest_bug and set the return to NULL. Still
  34. * it may happen as a result of emulator bug as well.
  35. */
  36. #undef SPICE_RING_PROD_ITEM
  37. #define SPICE_RING_PROD_ITEM(qxl, r, ret) { \
  38. uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
  39. if (prod >= ARRAY_SIZE((r)->items)) { \
  40. qxl_set_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \
  41. "%u >= %zu", prod, ARRAY_SIZE((r)->items)); \
  42. ret = NULL; \
  43. } else { \
  44. ret = &(r)->items[prod].el; \
  45. } \
  46. }
  47. #undef SPICE_RING_CONS_ITEM
  48. #define SPICE_RING_CONS_ITEM(qxl, r, ret) { \
  49. uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
  50. if (cons >= ARRAY_SIZE((r)->items)) { \
  51. qxl_set_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \
  52. "%u >= %zu", cons, ARRAY_SIZE((r)->items)); \
  53. ret = NULL; \
  54. } else { \
  55. ret = &(r)->items[cons].el; \
  56. } \
  57. }
  58. #undef ALIGN
  59. #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
  60. #define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9"
  61. #define QXL_MODE(_x, _y, _b, _o) \
  62. { .x_res = _x, \
  63. .y_res = _y, \
  64. .bits = _b, \
  65. .stride = (_x) * (_b) / 8, \
  66. .x_mili = PIXEL_SIZE * (_x), \
  67. .y_mili = PIXEL_SIZE * (_y), \
  68. .orientation = _o, \
  69. }
  70. #define QXL_MODE_16_32(x_res, y_res, orientation) \
  71. QXL_MODE(x_res, y_res, 16, orientation), \
  72. QXL_MODE(x_res, y_res, 32, orientation)
  73. #define QXL_MODE_EX(x_res, y_res) \
  74. QXL_MODE_16_32(x_res, y_res, 0), \
  75. QXL_MODE_16_32(x_res, y_res, 1)
  76. static QXLMode qxl_modes[] = {
  77. QXL_MODE_EX(640, 480),
  78. QXL_MODE_EX(800, 480),
  79. QXL_MODE_EX(800, 600),
  80. QXL_MODE_EX(832, 624),
  81. QXL_MODE_EX(960, 640),
  82. QXL_MODE_EX(1024, 600),
  83. QXL_MODE_EX(1024, 768),
  84. QXL_MODE_EX(1152, 864),
  85. QXL_MODE_EX(1152, 870),
  86. QXL_MODE_EX(1280, 720),
  87. QXL_MODE_EX(1280, 760),
  88. QXL_MODE_EX(1280, 768),
  89. QXL_MODE_EX(1280, 800),
  90. QXL_MODE_EX(1280, 960),
  91. QXL_MODE_EX(1280, 1024),
  92. QXL_MODE_EX(1360, 768),
  93. QXL_MODE_EX(1366, 768),
  94. QXL_MODE_EX(1400, 1050),
  95. QXL_MODE_EX(1440, 900),
  96. QXL_MODE_EX(1600, 900),
  97. QXL_MODE_EX(1600, 1200),
  98. QXL_MODE_EX(1680, 1050),
  99. QXL_MODE_EX(1920, 1080),
  100. /* these modes need more than 8 MB video memory */
  101. QXL_MODE_EX(1920, 1200),
  102. QXL_MODE_EX(1920, 1440),
  103. QXL_MODE_EX(2000, 2000),
  104. QXL_MODE_EX(2048, 1536),
  105. QXL_MODE_EX(2048, 2048),
  106. QXL_MODE_EX(2560, 1440),
  107. QXL_MODE_EX(2560, 1600),
  108. /* these modes need more than 16 MB video memory */
  109. QXL_MODE_EX(2560, 2048),
  110. QXL_MODE_EX(2800, 2100),
  111. QXL_MODE_EX(3200, 2400),
  112. QXL_MODE_EX(3840, 2160), /* 4k mainstream */
  113. QXL_MODE_EX(4096, 2160), /* 4k */
  114. QXL_MODE_EX(7680, 4320), /* 8k mainstream */
  115. QXL_MODE_EX(8192, 4320), /* 8k */
  116. };
  117. static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
  118. static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
  119. static void qxl_reset_memslots(PCIQXLDevice *d);
  120. static void qxl_reset_surfaces(PCIQXLDevice *d);
  121. static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
  122. void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
  123. {
  124. trace_qxl_set_guest_bug(qxl->id);
  125. qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
  126. qxl->guest_bug = 1;
  127. if (qxl->guestdebug) {
  128. va_list ap;
  129. va_start(ap, msg);
  130. fprintf(stderr, "qxl-%d: guest bug: ", qxl->id);
  131. vfprintf(stderr, msg, ap);
  132. fprintf(stderr, "\n");
  133. va_end(ap);
  134. }
  135. }
  136. static void qxl_clear_guest_bug(PCIQXLDevice *qxl)
  137. {
  138. qxl->guest_bug = 0;
  139. }
  140. void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
  141. struct QXLRect *area, struct QXLRect *dirty_rects,
  142. uint32_t num_dirty_rects,
  143. uint32_t clear_dirty_region,
  144. qxl_async_io async, struct QXLCookie *cookie)
  145. {
  146. trace_qxl_spice_update_area(qxl->id, surface_id, area->left, area->right,
  147. area->top, area->bottom);
  148. trace_qxl_spice_update_area_rest(qxl->id, num_dirty_rects,
  149. clear_dirty_region);
  150. if (async == QXL_SYNC) {
  151. spice_qxl_update_area(&qxl->ssd.qxl, surface_id, area,
  152. dirty_rects, num_dirty_rects, clear_dirty_region);
  153. } else {
  154. assert(cookie != NULL);
  155. spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
  156. clear_dirty_region, (uintptr_t)cookie);
  157. }
  158. }
  159. static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
  160. uint32_t id)
  161. {
  162. trace_qxl_spice_destroy_surface_wait_complete(qxl->id, id);
  163. qemu_mutex_lock(&qxl->track_lock);
  164. qxl->guest_surfaces.cmds[id] = 0;
  165. qxl->guest_surfaces.count--;
  166. qemu_mutex_unlock(&qxl->track_lock);
  167. }
  168. static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
  169. qxl_async_io async)
  170. {
  171. QXLCookie *cookie;
  172. trace_qxl_spice_destroy_surface_wait(qxl->id, id, async);
  173. if (async) {
  174. cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
  175. QXL_IO_DESTROY_SURFACE_ASYNC);
  176. cookie->u.surface_id = id;
  177. spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uintptr_t)cookie);
  178. } else {
  179. spice_qxl_destroy_surface_wait(&qxl->ssd.qxl, id);
  180. qxl_spice_destroy_surface_wait_complete(qxl, id);
  181. }
  182. }
  183. static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
  184. {
  185. trace_qxl_spice_flush_surfaces_async(qxl->id, qxl->guest_surfaces.count,
  186. qxl->num_free_res);
  187. spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
  188. (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
  189. QXL_IO_FLUSH_SURFACES_ASYNC));
  190. }
  191. void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
  192. uint32_t count)
  193. {
  194. trace_qxl_spice_loadvm_commands(qxl->id, ext, count);
  195. spice_qxl_loadvm_commands(&qxl->ssd.qxl, ext, count);
  196. }
  197. void qxl_spice_oom(PCIQXLDevice *qxl)
  198. {
  199. trace_qxl_spice_oom(qxl->id);
  200. spice_qxl_oom(&qxl->ssd.qxl);
  201. }
  202. void qxl_spice_reset_memslots(PCIQXLDevice *qxl)
  203. {
  204. trace_qxl_spice_reset_memslots(qxl->id);
  205. spice_qxl_reset_memslots(&qxl->ssd.qxl);
  206. }
  207. static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
  208. {
  209. trace_qxl_spice_destroy_surfaces_complete(qxl->id);
  210. qemu_mutex_lock(&qxl->track_lock);
  211. memset(qxl->guest_surfaces.cmds, 0,
  212. sizeof(qxl->guest_surfaces.cmds[0]) * qxl->ssd.num_surfaces);
  213. qxl->guest_surfaces.count = 0;
  214. qemu_mutex_unlock(&qxl->track_lock);
  215. }
  216. static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
  217. {
  218. trace_qxl_spice_destroy_surfaces(qxl->id, async);
  219. if (async) {
  220. spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
  221. (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
  222. QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
  223. } else {
  224. spice_qxl_destroy_surfaces(&qxl->ssd.qxl);
  225. qxl_spice_destroy_surfaces_complete(qxl);
  226. }
  227. }
  228. static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
  229. {
  230. trace_qxl_spice_monitors_config(qxl->id);
  231. if (replay) {
  232. /*
  233. * don't use QXL_COOKIE_TYPE_IO:
  234. * - we are not running yet (post_load), we will assert
  235. * in send_events
  236. * - this is not a guest io, but a reply, so async_io isn't set.
  237. */
  238. spice_qxl_monitors_config_async(&qxl->ssd.qxl,
  239. qxl->guest_monitors_config,
  240. MEMSLOT_GROUP_GUEST,
  241. (uintptr_t)qxl_cookie_new(
  242. QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
  243. 0));
  244. } else {
  245. qxl->guest_monitors_config = qxl->ram->monitors_config;
  246. spice_qxl_monitors_config_async(&qxl->ssd.qxl,
  247. qxl->ram->monitors_config,
  248. MEMSLOT_GROUP_GUEST,
  249. (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
  250. QXL_IO_MONITORS_CONFIG_ASYNC));
  251. }
  252. }
  253. void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
  254. {
  255. trace_qxl_spice_reset_image_cache(qxl->id);
  256. spice_qxl_reset_image_cache(&qxl->ssd.qxl);
  257. }
  258. void qxl_spice_reset_cursor(PCIQXLDevice *qxl)
  259. {
  260. trace_qxl_spice_reset_cursor(qxl->id);
  261. spice_qxl_reset_cursor(&qxl->ssd.qxl);
  262. qemu_mutex_lock(&qxl->track_lock);
  263. qxl->guest_cursor = 0;
  264. qemu_mutex_unlock(&qxl->track_lock);
  265. if (qxl->ssd.cursor) {
  266. cursor_put(qxl->ssd.cursor);
  267. }
  268. qxl->ssd.cursor = cursor_builtin_hidden();
  269. }
  270. static inline uint32_t msb_mask(uint32_t val)
  271. {
  272. uint32_t mask;
  273. do {
  274. mask = ~(val - 1) & val;
  275. val &= ~mask;
  276. } while (mask < val);
  277. return mask;
  278. }
  279. static ram_addr_t qxl_rom_size(void)
  280. {
  281. uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) +
  282. sizeof(qxl_modes);
  283. uint32_t rom_size = 8192; /* two pages */
  284. QEMU_BUILD_BUG_ON(required_rom_size > rom_size);
  285. return rom_size;
  286. }
  287. static void init_qxl_rom(PCIQXLDevice *d)
  288. {
  289. QXLRom *rom = memory_region_get_ram_ptr(&d->rom_bar);
  290. QXLModes *modes = (QXLModes *)(rom + 1);
  291. uint32_t ram_header_size;
  292. uint32_t surface0_area_size;
  293. uint32_t num_pages;
  294. uint32_t fb;
  295. int i, n;
  296. memset(rom, 0, d->rom_size);
  297. rom->magic = cpu_to_le32(QXL_ROM_MAGIC);
  298. rom->id = cpu_to_le32(d->id);
  299. rom->log_level = cpu_to_le32(d->guestdebug);
  300. rom->modes_offset = cpu_to_le32(sizeof(QXLRom));
  301. rom->slot_gen_bits = MEMSLOT_GENERATION_BITS;
  302. rom->slot_id_bits = MEMSLOT_SLOT_BITS;
  303. rom->slots_start = 1;
  304. rom->slots_end = NUM_MEMSLOTS - 1;
  305. rom->n_surfaces = cpu_to_le32(d->ssd.num_surfaces);
  306. for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) {
  307. fb = qxl_modes[i].y_res * qxl_modes[i].stride;
  308. if (fb > d->vgamem_size) {
  309. continue;
  310. }
  311. modes->modes[n].id = cpu_to_le32(i);
  312. modes->modes[n].x_res = cpu_to_le32(qxl_modes[i].x_res);
  313. modes->modes[n].y_res = cpu_to_le32(qxl_modes[i].y_res);
  314. modes->modes[n].bits = cpu_to_le32(qxl_modes[i].bits);
  315. modes->modes[n].stride = cpu_to_le32(qxl_modes[i].stride);
  316. modes->modes[n].x_mili = cpu_to_le32(qxl_modes[i].x_mili);
  317. modes->modes[n].y_mili = cpu_to_le32(qxl_modes[i].y_mili);
  318. modes->modes[n].orientation = cpu_to_le32(qxl_modes[i].orientation);
  319. n++;
  320. }
  321. modes->n_modes = cpu_to_le32(n);
  322. ram_header_size = ALIGN(sizeof(QXLRam), 4096);
  323. surface0_area_size = ALIGN(d->vgamem_size, 4096);
  324. num_pages = d->vga.vram_size;
  325. num_pages -= ram_header_size;
  326. num_pages -= surface0_area_size;
  327. num_pages = num_pages / QXL_PAGE_SIZE;
  328. rom->draw_area_offset = cpu_to_le32(0);
  329. rom->surface0_area_size = cpu_to_le32(surface0_area_size);
  330. rom->pages_offset = cpu_to_le32(surface0_area_size);
  331. rom->num_pages = cpu_to_le32(num_pages);
  332. rom->ram_header_offset = cpu_to_le32(d->vga.vram_size - ram_header_size);
  333. d->shadow_rom = *rom;
  334. d->rom = rom;
  335. d->modes = modes;
  336. }
  337. static void init_qxl_ram(PCIQXLDevice *d)
  338. {
  339. uint8_t *buf;
  340. uint64_t *item;
  341. buf = d->vga.vram_ptr;
  342. d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
  343. d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC);
  344. d->ram->int_pending = cpu_to_le32(0);
  345. d->ram->int_mask = cpu_to_le32(0);
  346. d->ram->update_surface = 0;
  347. d->ram->monitors_config = 0;
  348. SPICE_RING_INIT(&d->ram->cmd_ring);
  349. SPICE_RING_INIT(&d->ram->cursor_ring);
  350. SPICE_RING_INIT(&d->ram->release_ring);
  351. SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item);
  352. assert(item);
  353. *item = 0;
  354. qxl_ring_set_dirty(d);
  355. }
  356. /* can be called from spice server thread context */
  357. static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
  358. {
  359. memory_region_set_dirty(mr, addr, end - addr);
  360. }
  361. static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
  362. {
  363. qxl_set_dirty(&qxl->rom_bar, 0, qxl->rom_size);
  364. }
  365. /* called from spice server thread context only */
  366. static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
  367. {
  368. void *base = qxl->vga.vram_ptr;
  369. intptr_t offset;
  370. offset = ptr - base;
  371. assert(offset < qxl->vga.vram_size);
  372. qxl_set_dirty(&qxl->vga.vram, offset, offset + 3);
  373. }
  374. /* can be called from spice server thread context */
  375. static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
  376. {
  377. ram_addr_t addr = qxl->shadow_rom.ram_header_offset;
  378. ram_addr_t end = qxl->vga.vram_size;
  379. qxl_set_dirty(&qxl->vga.vram, addr, end);
  380. }
  381. /*
  382. * keep track of some command state, for savevm/loadvm.
  383. * called from spice server thread context only
  384. */
  385. static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
  386. {
  387. switch (le32_to_cpu(ext->cmd.type)) {
  388. case QXL_CMD_SURFACE:
  389. {
  390. QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
  391. if (!cmd) {
  392. return 1;
  393. }
  394. uint32_t id = le32_to_cpu(cmd->surface_id);
  395. if (id >= qxl->ssd.num_surfaces) {
  396. qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id,
  397. qxl->ssd.num_surfaces);
  398. return 1;
  399. }
  400. if (cmd->type == QXL_SURFACE_CMD_CREATE &&
  401. (cmd->u.surface_create.stride & 0x03) != 0) {
  402. qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE stride = %d %% 4 != 0\n",
  403. cmd->u.surface_create.stride);
  404. return 1;
  405. }
  406. qemu_mutex_lock(&qxl->track_lock);
  407. if (cmd->type == QXL_SURFACE_CMD_CREATE) {
  408. qxl->guest_surfaces.cmds[id] = ext->cmd.data;
  409. qxl->guest_surfaces.count++;
  410. if (qxl->guest_surfaces.max < qxl->guest_surfaces.count)
  411. qxl->guest_surfaces.max = qxl->guest_surfaces.count;
  412. }
  413. if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
  414. qxl->guest_surfaces.cmds[id] = 0;
  415. qxl->guest_surfaces.count--;
  416. }
  417. qemu_mutex_unlock(&qxl->track_lock);
  418. break;
  419. }
  420. case QXL_CMD_CURSOR:
  421. {
  422. QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
  423. if (!cmd) {
  424. return 1;
  425. }
  426. if (cmd->type == QXL_CURSOR_SET) {
  427. qemu_mutex_lock(&qxl->track_lock);
  428. qxl->guest_cursor = ext->cmd.data;
  429. qemu_mutex_unlock(&qxl->track_lock);
  430. }
  431. break;
  432. }
  433. }
  434. return 0;
  435. }
  436. /* spice display interface callbacks */
  437. static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
  438. {
  439. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  440. trace_qxl_interface_attach_worker(qxl->id);
  441. qxl->ssd.worker = qxl_worker;
  442. }
  443. static void interface_set_compression_level(QXLInstance *sin, int level)
  444. {
  445. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  446. trace_qxl_interface_set_compression_level(qxl->id, level);
  447. qxl->shadow_rom.compression_level = cpu_to_le32(level);
  448. qxl->rom->compression_level = cpu_to_le32(level);
  449. qxl_rom_set_dirty(qxl);
  450. }
  451. static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
  452. {
  453. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  454. trace_qxl_interface_set_mm_time(qxl->id, mm_time);
  455. qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
  456. qxl->rom->mm_clock = cpu_to_le32(mm_time);
  457. qxl_rom_set_dirty(qxl);
  458. }
  459. static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
  460. {
  461. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  462. trace_qxl_interface_get_init_info(qxl->id);
  463. info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
  464. info->memslot_id_bits = MEMSLOT_SLOT_BITS;
  465. info->num_memslots = NUM_MEMSLOTS;
  466. info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
  467. info->internal_groupslot_id = 0;
  468. info->qxl_ram_size =
  469. le32_to_cpu(qxl->shadow_rom.num_pages) << QXL_PAGE_BITS;
  470. info->n_surfaces = qxl->ssd.num_surfaces;
  471. }
  472. static const char *qxl_mode_to_string(int mode)
  473. {
  474. switch (mode) {
  475. case QXL_MODE_COMPAT:
  476. return "compat";
  477. case QXL_MODE_NATIVE:
  478. return "native";
  479. case QXL_MODE_UNDEFINED:
  480. return "undefined";
  481. case QXL_MODE_VGA:
  482. return "vga";
  483. }
  484. return "INVALID";
  485. }
  486. static const char *io_port_to_string(uint32_t io_port)
  487. {
  488. if (io_port >= QXL_IO_RANGE_SIZE) {
  489. return "out of range";
  490. }
  491. static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = {
  492. [QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD",
  493. [QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR",
  494. [QXL_IO_UPDATE_AREA] = "QXL_IO_UPDATE_AREA",
  495. [QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ",
  496. [QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM",
  497. [QXL_IO_RESET] = "QXL_IO_RESET",
  498. [QXL_IO_SET_MODE] = "QXL_IO_SET_MODE",
  499. [QXL_IO_LOG] = "QXL_IO_LOG",
  500. [QXL_IO_MEMSLOT_ADD] = "QXL_IO_MEMSLOT_ADD",
  501. [QXL_IO_MEMSLOT_DEL] = "QXL_IO_MEMSLOT_DEL",
  502. [QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY",
  503. [QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY",
  504. [QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY",
  505. [QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY",
  506. [QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT",
  507. [QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES",
  508. [QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC",
  509. [QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC",
  510. [QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC",
  511. [QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC",
  512. [QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC",
  513. [QXL_IO_DESTROY_ALL_SURFACES_ASYNC]
  514. = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
  515. [QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC",
  516. [QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE",
  517. [QXL_IO_MONITORS_CONFIG_ASYNC] = "QXL_IO_MONITORS_CONFIG_ASYNC",
  518. };
  519. return io_port_to_string[io_port];
  520. }
  521. /* called from spice server thread context only */
  522. static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
  523. {
  524. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  525. SimpleSpiceUpdate *update;
  526. QXLCommandRing *ring;
  527. QXLCommand *cmd;
  528. int notify, ret;
  529. trace_qxl_ring_command_check(qxl->id, qxl_mode_to_string(qxl->mode));
  530. switch (qxl->mode) {
  531. case QXL_MODE_VGA:
  532. ret = false;
  533. qemu_mutex_lock(&qxl->ssd.lock);
  534. update = QTAILQ_FIRST(&qxl->ssd.updates);
  535. if (update != NULL) {
  536. QTAILQ_REMOVE(&qxl->ssd.updates, update, next);
  537. *ext = update->ext;
  538. ret = true;
  539. }
  540. qemu_mutex_unlock(&qxl->ssd.lock);
  541. if (ret) {
  542. trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
  543. qxl_log_command(qxl, "vga", ext);
  544. }
  545. return ret;
  546. case QXL_MODE_COMPAT:
  547. case QXL_MODE_NATIVE:
  548. case QXL_MODE_UNDEFINED:
  549. ring = &qxl->ram->cmd_ring;
  550. if (qxl->guest_bug || SPICE_RING_IS_EMPTY(ring)) {
  551. return false;
  552. }
  553. SPICE_RING_CONS_ITEM(qxl, ring, cmd);
  554. if (!cmd) {
  555. return false;
  556. }
  557. ext->cmd = *cmd;
  558. ext->group_id = MEMSLOT_GROUP_GUEST;
  559. ext->flags = qxl->cmdflags;
  560. SPICE_RING_POP(ring, notify);
  561. qxl_ring_set_dirty(qxl);
  562. if (notify) {
  563. qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY);
  564. }
  565. qxl->guest_primary.commands++;
  566. qxl_track_command(qxl, ext);
  567. qxl_log_command(qxl, "cmd", ext);
  568. trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
  569. return true;
  570. default:
  571. return false;
  572. }
  573. }
  574. /* called from spice server thread context only */
  575. static int interface_req_cmd_notification(QXLInstance *sin)
  576. {
  577. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  578. int wait = 1;
  579. trace_qxl_ring_command_req_notification(qxl->id);
  580. switch (qxl->mode) {
  581. case QXL_MODE_COMPAT:
  582. case QXL_MODE_NATIVE:
  583. case QXL_MODE_UNDEFINED:
  584. SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait);
  585. qxl_ring_set_dirty(qxl);
  586. break;
  587. default:
  588. /* nothing */
  589. break;
  590. }
  591. return wait;
  592. }
  593. /* called from spice server thread context only */
  594. static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
  595. {
  596. QXLReleaseRing *ring = &d->ram->release_ring;
  597. uint64_t *item;
  598. int notify;
  599. #define QXL_FREE_BUNCH_SIZE 32
  600. if (ring->prod - ring->cons + 1 == ring->num_items) {
  601. /* ring full -- can't push */
  602. return;
  603. }
  604. if (!flush && d->oom_running) {
  605. /* collect everything from oom handler before pushing */
  606. return;
  607. }
  608. if (!flush && d->num_free_res < QXL_FREE_BUNCH_SIZE) {
  609. /* collect a bit more before pushing */
  610. return;
  611. }
  612. SPICE_RING_PUSH(ring, notify);
  613. trace_qxl_ring_res_push(d->id, qxl_mode_to_string(d->mode),
  614. d->guest_surfaces.count, d->num_free_res,
  615. d->last_release, notify ? "yes" : "no");
  616. trace_qxl_ring_res_push_rest(d->id, ring->prod - ring->cons,
  617. ring->num_items, ring->prod, ring->cons);
  618. if (notify) {
  619. qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
  620. }
  621. SPICE_RING_PROD_ITEM(d, ring, item);
  622. if (!item) {
  623. return;
  624. }
  625. *item = 0;
  626. d->num_free_res = 0;
  627. d->last_release = NULL;
  628. qxl_ring_set_dirty(d);
  629. }
  630. /* called from spice server thread context only */
  631. static void interface_release_resource(QXLInstance *sin,
  632. struct QXLReleaseInfoExt ext)
  633. {
  634. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  635. QXLReleaseRing *ring;
  636. uint64_t *item, id;
  637. if (ext.group_id == MEMSLOT_GROUP_HOST) {
  638. /* host group -> vga mode update request */
  639. QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id);
  640. SimpleSpiceUpdate *update;
  641. g_assert(cmdext->cmd.type == QXL_CMD_DRAW);
  642. update = container_of(cmdext, SimpleSpiceUpdate, ext);
  643. qemu_spice_destroy_update(&qxl->ssd, update);
  644. return;
  645. }
  646. /*
  647. * ext->info points into guest-visible memory
  648. * pci bar 0, $command.release_info
  649. */
  650. ring = &qxl->ram->release_ring;
  651. SPICE_RING_PROD_ITEM(qxl, ring, item);
  652. if (!item) {
  653. return;
  654. }
  655. if (*item == 0) {
  656. /* stick head into the ring */
  657. id = ext.info->id;
  658. ext.info->next = 0;
  659. qxl_ram_set_dirty(qxl, &ext.info->next);
  660. *item = id;
  661. qxl_ring_set_dirty(qxl);
  662. } else {
  663. /* append item to the list */
  664. qxl->last_release->next = ext.info->id;
  665. qxl_ram_set_dirty(qxl, &qxl->last_release->next);
  666. ext.info->next = 0;
  667. qxl_ram_set_dirty(qxl, &ext.info->next);
  668. }
  669. qxl->last_release = ext.info;
  670. qxl->num_free_res++;
  671. trace_qxl_ring_res_put(qxl->id, qxl->num_free_res);
  672. qxl_push_free_res(qxl, 0);
  673. }
  674. /* called from spice server thread context only */
  675. static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
  676. {
  677. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  678. QXLCursorRing *ring;
  679. QXLCommand *cmd;
  680. int notify;
  681. trace_qxl_ring_cursor_check(qxl->id, qxl_mode_to_string(qxl->mode));
  682. switch (qxl->mode) {
  683. case QXL_MODE_COMPAT:
  684. case QXL_MODE_NATIVE:
  685. case QXL_MODE_UNDEFINED:
  686. ring = &qxl->ram->cursor_ring;
  687. if (SPICE_RING_IS_EMPTY(ring)) {
  688. return false;
  689. }
  690. SPICE_RING_CONS_ITEM(qxl, ring, cmd);
  691. if (!cmd) {
  692. return false;
  693. }
  694. ext->cmd = *cmd;
  695. ext->group_id = MEMSLOT_GROUP_GUEST;
  696. ext->flags = qxl->cmdflags;
  697. SPICE_RING_POP(ring, notify);
  698. qxl_ring_set_dirty(qxl);
  699. if (notify) {
  700. qxl_send_events(qxl, QXL_INTERRUPT_CURSOR);
  701. }
  702. qxl->guest_primary.commands++;
  703. qxl_track_command(qxl, ext);
  704. qxl_log_command(qxl, "csr", ext);
  705. if (qxl->id == 0) {
  706. qxl_render_cursor(qxl, ext);
  707. }
  708. trace_qxl_ring_cursor_get(qxl->id, qxl_mode_to_string(qxl->mode));
  709. return true;
  710. default:
  711. return false;
  712. }
  713. }
  714. /* called from spice server thread context only */
  715. static int interface_req_cursor_notification(QXLInstance *sin)
  716. {
  717. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  718. int wait = 1;
  719. trace_qxl_ring_cursor_req_notification(qxl->id);
  720. switch (qxl->mode) {
  721. case QXL_MODE_COMPAT:
  722. case QXL_MODE_NATIVE:
  723. case QXL_MODE_UNDEFINED:
  724. SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait);
  725. qxl_ring_set_dirty(qxl);
  726. break;
  727. default:
  728. /* nothing */
  729. break;
  730. }
  731. return wait;
  732. }
  733. /* called from spice server thread context */
  734. static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
  735. {
  736. /*
  737. * Called by spice-server as a result of a QXL_CMD_UPDATE which is not in
  738. * use by xf86-video-qxl and is defined out in the qxl windows driver.
  739. * Probably was at some earlier version that is prior to git start (2009),
  740. * and is still guest trigerrable.
  741. */
  742. fprintf(stderr, "%s: deprecated\n", __func__);
  743. }
  744. /* called from spice server thread context only */
  745. static int interface_flush_resources(QXLInstance *sin)
  746. {
  747. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  748. int ret;
  749. ret = qxl->num_free_res;
  750. if (ret) {
  751. qxl_push_free_res(qxl, 1);
  752. }
  753. return ret;
  754. }
  755. static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
  756. /* called from spice server thread context only */
  757. static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
  758. {
  759. uint32_t current_async;
  760. qemu_mutex_lock(&qxl->async_lock);
  761. current_async = qxl->current_async;
  762. qxl->current_async = QXL_UNDEFINED_IO;
  763. qemu_mutex_unlock(&qxl->async_lock);
  764. trace_qxl_interface_async_complete_io(qxl->id, current_async, cookie);
  765. if (!cookie) {
  766. fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
  767. return;
  768. }
  769. if (cookie && current_async != cookie->io) {
  770. fprintf(stderr,
  771. "qxl: %s: error: current_async = %d != %"
  772. PRId64 " = cookie->io\n", __func__, current_async, cookie->io);
  773. }
  774. switch (current_async) {
  775. case QXL_IO_MEMSLOT_ADD_ASYNC:
  776. case QXL_IO_DESTROY_PRIMARY_ASYNC:
  777. case QXL_IO_UPDATE_AREA_ASYNC:
  778. case QXL_IO_FLUSH_SURFACES_ASYNC:
  779. case QXL_IO_MONITORS_CONFIG_ASYNC:
  780. break;
  781. case QXL_IO_CREATE_PRIMARY_ASYNC:
  782. qxl_create_guest_primary_complete(qxl);
  783. break;
  784. case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
  785. qxl_spice_destroy_surfaces_complete(qxl);
  786. break;
  787. case QXL_IO_DESTROY_SURFACE_ASYNC:
  788. qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
  789. break;
  790. default:
  791. fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
  792. current_async);
  793. }
  794. qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
  795. }
  796. /* called from spice server thread context only */
  797. static void interface_update_area_complete(QXLInstance *sin,
  798. uint32_t surface_id,
  799. QXLRect *dirty, uint32_t num_updated_rects)
  800. {
  801. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  802. int i;
  803. int qxl_i;
  804. qemu_mutex_lock(&qxl->ssd.lock);
  805. if (surface_id != 0 || !qxl->render_update_cookie_num) {
  806. qemu_mutex_unlock(&qxl->ssd.lock);
  807. return;
  808. }
  809. trace_qxl_interface_update_area_complete(qxl->id, surface_id, dirty->left,
  810. dirty->right, dirty->top, dirty->bottom);
  811. trace_qxl_interface_update_area_complete_rest(qxl->id, num_updated_rects);
  812. if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
  813. /*
  814. * overflow - treat this as a full update. Not expected to be common.
  815. */
  816. trace_qxl_interface_update_area_complete_overflow(qxl->id,
  817. QXL_NUM_DIRTY_RECTS);
  818. qxl->guest_primary.resized = 1;
  819. }
  820. if (qxl->guest_primary.resized) {
  821. /*
  822. * Don't bother copying or scheduling the bh since we will flip
  823. * the whole area anyway on completion of the update_area async call
  824. */
  825. qemu_mutex_unlock(&qxl->ssd.lock);
  826. return;
  827. }
  828. qxl_i = qxl->num_dirty_rects;
  829. for (i = 0; i < num_updated_rects; i++) {
  830. qxl->dirty[qxl_i++] = dirty[i];
  831. }
  832. qxl->num_dirty_rects += num_updated_rects;
  833. trace_qxl_interface_update_area_complete_schedule_bh(qxl->id,
  834. qxl->num_dirty_rects);
  835. qemu_bh_schedule(qxl->update_area_bh);
  836. qemu_mutex_unlock(&qxl->ssd.lock);
  837. }
  838. /* called from spice server thread context only */
  839. static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
  840. {
  841. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  842. QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token;
  843. switch (cookie->type) {
  844. case QXL_COOKIE_TYPE_IO:
  845. interface_async_complete_io(qxl, cookie);
  846. g_free(cookie);
  847. break;
  848. case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
  849. qxl_render_update_area_done(qxl, cookie);
  850. break;
  851. case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG:
  852. break;
  853. default:
  854. fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
  855. __func__, cookie->type);
  856. g_free(cookie);
  857. }
  858. }
  859. /* called from spice server thread context only */
  860. static void interface_set_client_capabilities(QXLInstance *sin,
  861. uint8_t client_present,
  862. uint8_t caps[58])
  863. {
  864. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  865. if (qxl->revision < 4) {
  866. trace_qxl_set_client_capabilities_unsupported_by_revision(qxl->id,
  867. qxl->revision);
  868. return;
  869. }
  870. if (runstate_check(RUN_STATE_INMIGRATE) ||
  871. runstate_check(RUN_STATE_POSTMIGRATE)) {
  872. return;
  873. }
  874. qxl->shadow_rom.client_present = client_present;
  875. memcpy(qxl->shadow_rom.client_capabilities, caps,
  876. sizeof(qxl->shadow_rom.client_capabilities));
  877. qxl->rom->client_present = client_present;
  878. memcpy(qxl->rom->client_capabilities, caps,
  879. sizeof(qxl->rom->client_capabilities));
  880. qxl_rom_set_dirty(qxl);
  881. qxl_send_events(qxl, QXL_INTERRUPT_CLIENT);
  882. }
  883. static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
  884. {
  885. /*
  886. * zlib xors the seed with 0xffffffff, and xors the result
  887. * again with 0xffffffff; Both are not done with linux's crc32,
  888. * which we want to be compatible with, so undo that.
  889. */
  890. return crc32(0xffffffff, p, len) ^ 0xffffffff;
  891. }
  892. /* called from main context only */
  893. static int interface_client_monitors_config(QXLInstance *sin,
  894. VDAgentMonitorsConfig *monitors_config)
  895. {
  896. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  897. QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
  898. int i;
  899. if (qxl->revision < 4) {
  900. trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
  901. qxl->revision);
  902. return 0;
  903. }
  904. /*
  905. * Older windows drivers set int_mask to 0 when their ISR is called,
  906. * then later set it to ~0. So it doesn't relate to the actual interrupts
  907. * handled. However, they are old, so clearly they don't support this
  908. * interrupt
  909. */
  910. if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
  911. !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {
  912. trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
  913. qxl->ram->int_mask,
  914. monitors_config);
  915. return 0;
  916. }
  917. if (!monitors_config) {
  918. return 1;
  919. }
  920. memset(&rom->client_monitors_config, 0,
  921. sizeof(rom->client_monitors_config));
  922. rom->client_monitors_config.count = monitors_config->num_of_monitors;
  923. /* monitors_config->flags ignored */
  924. if (rom->client_monitors_config.count >=
  925. ARRAY_SIZE(rom->client_monitors_config.heads)) {
  926. trace_qxl_client_monitors_config_capped(qxl->id,
  927. monitors_config->num_of_monitors,
  928. ARRAY_SIZE(rom->client_monitors_config.heads));
  929. rom->client_monitors_config.count =
  930. ARRAY_SIZE(rom->client_monitors_config.heads);
  931. }
  932. for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
  933. VDAgentMonConfig *monitor = &monitors_config->monitors[i];
  934. QXLURect *rect = &rom->client_monitors_config.heads[i];
  935. /* monitor->depth ignored */
  936. rect->left = monitor->x;
  937. rect->top = monitor->y;
  938. rect->right = monitor->x + monitor->width;
  939. rect->bottom = monitor->y + monitor->height;
  940. }
  941. rom->client_monitors_config_crc = qxl_crc32(
  942. (const uint8_t *)&rom->client_monitors_config,
  943. sizeof(rom->client_monitors_config));
  944. trace_qxl_client_monitors_config_crc(qxl->id,
  945. sizeof(rom->client_monitors_config),
  946. rom->client_monitors_config_crc);
  947. trace_qxl_interrupt_client_monitors_config(qxl->id,
  948. rom->client_monitors_config.count,
  949. rom->client_monitors_config.heads);
  950. qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
  951. return 1;
  952. }
  953. static const QXLInterface qxl_interface = {
  954. .base.type = SPICE_INTERFACE_QXL,
  955. .base.description = "qxl gpu",
  956. .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
  957. .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
  958. .attache_worker = interface_attach_worker,
  959. .set_compression_level = interface_set_compression_level,
  960. .set_mm_time = interface_set_mm_time,
  961. .get_init_info = interface_get_init_info,
  962. /* the callbacks below are called from spice server thread context */
  963. .get_command = interface_get_command,
  964. .req_cmd_notification = interface_req_cmd_notification,
  965. .release_resource = interface_release_resource,
  966. .get_cursor_command = interface_get_cursor_command,
  967. .req_cursor_notification = interface_req_cursor_notification,
  968. .notify_update = interface_notify_update,
  969. .flush_resources = interface_flush_resources,
  970. .async_complete = interface_async_complete,
  971. .update_area_complete = interface_update_area_complete,
  972. .set_client_capabilities = interface_set_client_capabilities,
  973. .client_monitors_config = interface_client_monitors_config,
  974. };
  975. static void qxl_enter_vga_mode(PCIQXLDevice *d)
  976. {
  977. if (d->mode == QXL_MODE_VGA) {
  978. return;
  979. }
  980. trace_qxl_enter_vga_mode(d->id);
  981. #if SPICE_SERVER_VERSION >= 0x000c03 /* release 0.12.3 */
  982. spice_qxl_driver_unload(&d->ssd.qxl);
  983. #endif
  984. qemu_spice_create_host_primary(&d->ssd);
  985. d->mode = QXL_MODE_VGA;
  986. vga_dirty_log_start(&d->vga);
  987. graphic_hw_update(d->vga.con);
  988. }
  989. static void qxl_exit_vga_mode(PCIQXLDevice *d)
  990. {
  991. if (d->mode != QXL_MODE_VGA) {
  992. return;
  993. }
  994. trace_qxl_exit_vga_mode(d->id);
  995. vga_dirty_log_stop(&d->vga);
  996. qxl_destroy_primary(d, QXL_SYNC);
  997. }
  998. static void qxl_update_irq(PCIQXLDevice *d)
  999. {
  1000. uint32_t pending = le32_to_cpu(d->ram->int_pending);
  1001. uint32_t mask = le32_to_cpu(d->ram->int_mask);
  1002. int level = !!(pending & mask);
  1003. pci_set_irq(&d->pci, level);
  1004. qxl_ring_set_dirty(d);
  1005. }
  1006. static void qxl_check_state(PCIQXLDevice *d)
  1007. {
  1008. QXLRam *ram = d->ram;
  1009. int spice_display_running = qemu_spice_display_is_running(&d->ssd);
  1010. assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
  1011. assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
  1012. }
  1013. static void qxl_reset_state(PCIQXLDevice *d)
  1014. {
  1015. QXLRom *rom = d->rom;
  1016. qxl_check_state(d);
  1017. d->shadow_rom.update_id = cpu_to_le32(0);
  1018. *rom = d->shadow_rom;
  1019. qxl_rom_set_dirty(d);
  1020. init_qxl_ram(d);
  1021. d->num_free_res = 0;
  1022. d->last_release = NULL;
  1023. memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
  1024. qxl_update_irq(d);
  1025. }
  1026. static void qxl_soft_reset(PCIQXLDevice *d)
  1027. {
  1028. trace_qxl_soft_reset(d->id);
  1029. qxl_check_state(d);
  1030. qxl_clear_guest_bug(d);
  1031. d->current_async = QXL_UNDEFINED_IO;
  1032. if (d->id == 0) {
  1033. qxl_enter_vga_mode(d);
  1034. } else {
  1035. d->mode = QXL_MODE_UNDEFINED;
  1036. }
  1037. }
  1038. static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
  1039. {
  1040. bool startstop = qemu_spice_display_is_running(&d->ssd);
  1041. trace_qxl_hard_reset(d->id, loadvm);
  1042. if (startstop) {
  1043. qemu_spice_display_stop();
  1044. }
  1045. qxl_spice_reset_cursor(d);
  1046. qxl_spice_reset_image_cache(d);
  1047. qxl_reset_surfaces(d);
  1048. qxl_reset_memslots(d);
  1049. /* pre loadvm reset must not touch QXLRam. This lives in
  1050. * device memory, is migrated together with RAM and thus
  1051. * already loaded at this point */
  1052. if (!loadvm) {
  1053. qxl_reset_state(d);
  1054. }
  1055. qemu_spice_create_host_memslot(&d->ssd);
  1056. qxl_soft_reset(d);
  1057. if (startstop) {
  1058. qemu_spice_display_start();
  1059. }
  1060. }
  1061. static void qxl_reset_handler(DeviceState *dev)
  1062. {
  1063. PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
  1064. qxl_hard_reset(d, 0);
  1065. }
  1066. static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  1067. {
  1068. VGACommonState *vga = opaque;
  1069. PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
  1070. trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
  1071. if (qxl->mode != QXL_MODE_VGA) {
  1072. qxl_destroy_primary(qxl, QXL_SYNC);
  1073. qxl_soft_reset(qxl);
  1074. }
  1075. vga_ioport_write(opaque, addr, val);
  1076. }
  1077. static const MemoryRegionPortio qxl_vga_portio_list[] = {
  1078. { 0x04, 2, 1, .read = vga_ioport_read,
  1079. .write = qxl_vga_ioport_write }, /* 3b4 */
  1080. { 0x0a, 1, 1, .read = vga_ioport_read,
  1081. .write = qxl_vga_ioport_write }, /* 3ba */
  1082. { 0x10, 16, 1, .read = vga_ioport_read,
  1083. .write = qxl_vga_ioport_write }, /* 3c0 */
  1084. { 0x24, 2, 1, .read = vga_ioport_read,
  1085. .write = qxl_vga_ioport_write }, /* 3d4 */
  1086. { 0x2a, 1, 1, .read = vga_ioport_read,
  1087. .write = qxl_vga_ioport_write }, /* 3da */
  1088. PORTIO_END_OF_LIST(),
  1089. };
  1090. static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
  1091. qxl_async_io async)
  1092. {
  1093. static const int regions[] = {
  1094. QXL_RAM_RANGE_INDEX,
  1095. QXL_VRAM_RANGE_INDEX,
  1096. QXL_VRAM64_RANGE_INDEX,
  1097. };
  1098. uint64_t guest_start;
  1099. uint64_t guest_end;
  1100. int pci_region;
  1101. pcibus_t pci_start;
  1102. pcibus_t pci_end;
  1103. intptr_t virt_start;
  1104. QXLDevMemSlot memslot;
  1105. int i;
  1106. guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
  1107. guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
  1108. trace_qxl_memslot_add_guest(d->id, slot_id, guest_start, guest_end);
  1109. if (slot_id >= NUM_MEMSLOTS) {
  1110. qxl_set_guest_bug(d, "%s: slot_id >= NUM_MEMSLOTS %d >= %d", __func__,
  1111. slot_id, NUM_MEMSLOTS);
  1112. return 1;
  1113. }
  1114. if (guest_start > guest_end) {
  1115. qxl_set_guest_bug(d, "%s: guest_start > guest_end 0x%" PRIx64
  1116. " > 0x%" PRIx64, __func__, guest_start, guest_end);
  1117. return 1;
  1118. }
  1119. for (i = 0; i < ARRAY_SIZE(regions); i++) {
  1120. pci_region = regions[i];
  1121. pci_start = d->pci.io_regions[pci_region].addr;
  1122. pci_end = pci_start + d->pci.io_regions[pci_region].size;
  1123. /* mapped? */
  1124. if (pci_start == -1) {
  1125. continue;
  1126. }
  1127. /* start address in range ? */
  1128. if (guest_start < pci_start || guest_start > pci_end) {
  1129. continue;
  1130. }
  1131. /* end address in range ? */
  1132. if (guest_end > pci_end) {
  1133. continue;
  1134. }
  1135. /* passed */
  1136. break;
  1137. }
  1138. if (i == ARRAY_SIZE(regions)) {
  1139. qxl_set_guest_bug(d, "%s: finished loop without match", __func__);
  1140. return 1;
  1141. }
  1142. switch (pci_region) {
  1143. case QXL_RAM_RANGE_INDEX:
  1144. virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
  1145. break;
  1146. case QXL_VRAM_RANGE_INDEX:
  1147. case 4 /* vram 64bit */:
  1148. virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
  1149. break;
  1150. default:
  1151. /* should not happen */
  1152. qxl_set_guest_bug(d, "%s: pci_region = %d", __func__, pci_region);
  1153. return 1;
  1154. }
  1155. memslot.slot_id = slot_id;
  1156. memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
  1157. memslot.virt_start = virt_start + (guest_start - pci_start);
  1158. memslot.virt_end = virt_start + (guest_end - pci_start);
  1159. memslot.addr_delta = memslot.virt_start - delta;
  1160. memslot.generation = d->rom->slot_generation = 0;
  1161. qxl_rom_set_dirty(d);
  1162. qemu_spice_add_memslot(&d->ssd, &memslot, async);
  1163. d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
  1164. d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
  1165. d->guest_slots[slot_id].delta = delta;
  1166. d->guest_slots[slot_id].active = 1;
  1167. return 0;
  1168. }
  1169. static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
  1170. {
  1171. qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id);
  1172. d->guest_slots[slot_id].active = 0;
  1173. }
  1174. static void qxl_reset_memslots(PCIQXLDevice *d)
  1175. {
  1176. qxl_spice_reset_memslots(d);
  1177. memset(&d->guest_slots, 0, sizeof(d->guest_slots));
  1178. }
  1179. static void qxl_reset_surfaces(PCIQXLDevice *d)
  1180. {
  1181. trace_qxl_reset_surfaces(d->id);
  1182. d->mode = QXL_MODE_UNDEFINED;
  1183. qxl_spice_destroy_surfaces(d, QXL_SYNC);
  1184. }
  1185. /* can be also called from spice server thread context */
  1186. void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
  1187. {
  1188. uint64_t phys = le64_to_cpu(pqxl);
  1189. uint32_t slot = (phys >> (64 - 8)) & 0xff;
  1190. uint64_t offset = phys & 0xffffffffffff;
  1191. switch (group_id) {
  1192. case MEMSLOT_GROUP_HOST:
  1193. return (void *)(intptr_t)offset;
  1194. case MEMSLOT_GROUP_GUEST:
  1195. if (slot >= NUM_MEMSLOTS) {
  1196. qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
  1197. NUM_MEMSLOTS);
  1198. return NULL;
  1199. }
  1200. if (!qxl->guest_slots[slot].active) {
  1201. qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
  1202. return NULL;
  1203. }
  1204. if (offset < qxl->guest_slots[slot].delta) {
  1205. qxl_set_guest_bug(qxl,
  1206. "slot %d offset %"PRIu64" < delta %"PRIu64"\n",
  1207. slot, offset, qxl->guest_slots[slot].delta);
  1208. return NULL;
  1209. }
  1210. offset -= qxl->guest_slots[slot].delta;
  1211. if (offset > qxl->guest_slots[slot].size) {
  1212. qxl_set_guest_bug(qxl,
  1213. "slot %d offset %"PRIu64" > size %"PRIu64"\n",
  1214. slot, offset, qxl->guest_slots[slot].size);
  1215. return NULL;
  1216. }
  1217. return qxl->guest_slots[slot].ptr + offset;
  1218. }
  1219. return NULL;
  1220. }
  1221. static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
  1222. {
  1223. /* for local rendering */
  1224. qxl_render_resize(qxl);
  1225. }
  1226. static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
  1227. qxl_async_io async)
  1228. {
  1229. QXLDevSurfaceCreate surface;
  1230. QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
  1231. uint32_t requested_height = le32_to_cpu(sc->height);
  1232. int requested_stride = le32_to_cpu(sc->stride);
  1233. if (requested_stride == INT32_MIN ||
  1234. abs(requested_stride) * (uint64_t)requested_height
  1235. > qxl->vgamem_size) {
  1236. qxl_set_guest_bug(qxl, "%s: requested primary larger than framebuffer"
  1237. " stride %d x height %" PRIu32 " > %" PRIu32,
  1238. __func__, requested_stride, requested_height,
  1239. qxl->vgamem_size);
  1240. return;
  1241. }
  1242. if (qxl->mode == QXL_MODE_NATIVE) {
  1243. qxl_set_guest_bug(qxl, "%s: nop since already in QXL_MODE_NATIVE",
  1244. __func__);
  1245. }
  1246. qxl_exit_vga_mode(qxl);
  1247. surface.format = le32_to_cpu(sc->format);
  1248. surface.height = le32_to_cpu(sc->height);
  1249. surface.mem = le64_to_cpu(sc->mem);
  1250. surface.position = le32_to_cpu(sc->position);
  1251. surface.stride = le32_to_cpu(sc->stride);
  1252. surface.width = le32_to_cpu(sc->width);
  1253. surface.type = le32_to_cpu(sc->type);
  1254. surface.flags = le32_to_cpu(sc->flags);
  1255. trace_qxl_create_guest_primary(qxl->id, sc->width, sc->height, sc->mem,
  1256. sc->format, sc->position);
  1257. trace_qxl_create_guest_primary_rest(qxl->id, sc->stride, sc->type,
  1258. sc->flags);
  1259. if ((surface.stride & 0x3) != 0) {
  1260. qxl_set_guest_bug(qxl, "primary surface stride = %d %% 4 != 0",
  1261. surface.stride);
  1262. return;
  1263. }
  1264. surface.mouse_mode = true;
  1265. surface.group_id = MEMSLOT_GROUP_GUEST;
  1266. if (loadvm) {
  1267. surface.flags |= QXL_SURF_FLAG_KEEP_DATA;
  1268. }
  1269. qxl->mode = QXL_MODE_NATIVE;
  1270. qxl->cmdflags = 0;
  1271. qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async);
  1272. if (async == QXL_SYNC) {
  1273. qxl_create_guest_primary_complete(qxl);
  1274. }
  1275. }
  1276. /* return 1 if surface destoy was initiated (in QXL_ASYNC case) or
  1277. * done (in QXL_SYNC case), 0 otherwise. */
  1278. static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
  1279. {
  1280. if (d->mode == QXL_MODE_UNDEFINED) {
  1281. return 0;
  1282. }
  1283. trace_qxl_destroy_primary(d->id);
  1284. d->mode = QXL_MODE_UNDEFINED;
  1285. qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
  1286. qxl_spice_reset_cursor(d);
  1287. return 1;
  1288. }
  1289. static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm)
  1290. {
  1291. pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
  1292. pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start;
  1293. QXLMode *mode = d->modes->modes + modenr;
  1294. uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
  1295. QXLMemSlot slot = {
  1296. .mem_start = start,
  1297. .mem_end = end
  1298. };
  1299. if (modenr >= d->modes->n_modes) {
  1300. qxl_set_guest_bug(d, "mode number out of range");
  1301. return;
  1302. }
  1303. QXLSurfaceCreate surface = {
  1304. .width = mode->x_res,
  1305. .height = mode->y_res,
  1306. .stride = -mode->x_res * 4,
  1307. .format = SPICE_SURFACE_FMT_32_xRGB,
  1308. .flags = loadvm ? QXL_SURF_FLAG_KEEP_DATA : 0,
  1309. .mouse_mode = true,
  1310. .mem = devmem + d->shadow_rom.draw_area_offset,
  1311. };
  1312. trace_qxl_set_mode(d->id, modenr, mode->x_res, mode->y_res, mode->bits,
  1313. devmem);
  1314. if (!loadvm) {
  1315. qxl_hard_reset(d, 0);
  1316. }
  1317. d->guest_slots[0].slot = slot;
  1318. assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0);
  1319. d->guest_primary.surface = surface;
  1320. qxl_create_guest_primary(d, 0, QXL_SYNC);
  1321. d->mode = QXL_MODE_COMPAT;
  1322. d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
  1323. if (mode->bits == 16) {
  1324. d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP;
  1325. }
  1326. d->shadow_rom.mode = cpu_to_le32(modenr);
  1327. d->rom->mode = cpu_to_le32(modenr);
  1328. qxl_rom_set_dirty(d);
  1329. }
  1330. static void ioport_write(void *opaque, hwaddr addr,
  1331. uint64_t val, unsigned size)
  1332. {
  1333. PCIQXLDevice *d = opaque;
  1334. uint32_t io_port = addr;
  1335. qxl_async_io async = QXL_SYNC;
  1336. uint32_t orig_io_port = io_port;
  1337. if (d->guest_bug && io_port != QXL_IO_RESET) {
  1338. return;
  1339. }
  1340. if (d->revision <= QXL_REVISION_STABLE_V10 &&
  1341. io_port > QXL_IO_FLUSH_RELEASE) {
  1342. qxl_set_guest_bug(d, "unsupported io %d for revision %d\n",
  1343. io_port, d->revision);
  1344. return;
  1345. }
  1346. switch (io_port) {
  1347. case QXL_IO_RESET:
  1348. case QXL_IO_SET_MODE:
  1349. case QXL_IO_MEMSLOT_ADD:
  1350. case QXL_IO_MEMSLOT_DEL:
  1351. case QXL_IO_CREATE_PRIMARY:
  1352. case QXL_IO_UPDATE_IRQ:
  1353. case QXL_IO_LOG:
  1354. case QXL_IO_MEMSLOT_ADD_ASYNC:
  1355. case QXL_IO_CREATE_PRIMARY_ASYNC:
  1356. break;
  1357. default:
  1358. if (d->mode != QXL_MODE_VGA) {
  1359. break;
  1360. }
  1361. trace_qxl_io_unexpected_vga_mode(d->id,
  1362. addr, val, io_port_to_string(io_port));
  1363. /* be nice to buggy guest drivers */
  1364. if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
  1365. io_port < QXL_IO_RANGE_SIZE) {
  1366. qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
  1367. }
  1368. return;
  1369. }
  1370. /* we change the io_port to avoid ifdeffery in the main switch */
  1371. orig_io_port = io_port;
  1372. switch (io_port) {
  1373. case QXL_IO_UPDATE_AREA_ASYNC:
  1374. io_port = QXL_IO_UPDATE_AREA;
  1375. goto async_common;
  1376. case QXL_IO_MEMSLOT_ADD_ASYNC:
  1377. io_port = QXL_IO_MEMSLOT_ADD;
  1378. goto async_common;
  1379. case QXL_IO_CREATE_PRIMARY_ASYNC:
  1380. io_port = QXL_IO_CREATE_PRIMARY;
  1381. goto async_common;
  1382. case QXL_IO_DESTROY_PRIMARY_ASYNC:
  1383. io_port = QXL_IO_DESTROY_PRIMARY;
  1384. goto async_common;
  1385. case QXL_IO_DESTROY_SURFACE_ASYNC:
  1386. io_port = QXL_IO_DESTROY_SURFACE_WAIT;
  1387. goto async_common;
  1388. case QXL_IO_DESTROY_ALL_SURFACES_ASYNC:
  1389. io_port = QXL_IO_DESTROY_ALL_SURFACES;
  1390. goto async_common;
  1391. case QXL_IO_FLUSH_SURFACES_ASYNC:
  1392. case QXL_IO_MONITORS_CONFIG_ASYNC:
  1393. async_common:
  1394. async = QXL_ASYNC;
  1395. qemu_mutex_lock(&d->async_lock);
  1396. if (d->current_async != QXL_UNDEFINED_IO) {
  1397. qxl_set_guest_bug(d, "%d async started before last (%d) complete",
  1398. io_port, d->current_async);
  1399. qemu_mutex_unlock(&d->async_lock);
  1400. return;
  1401. }
  1402. d->current_async = orig_io_port;
  1403. qemu_mutex_unlock(&d->async_lock);
  1404. break;
  1405. default:
  1406. break;
  1407. }
  1408. trace_qxl_io_write(d->id, qxl_mode_to_string(d->mode),
  1409. addr, io_port_to_string(addr),
  1410. val, size, async);
  1411. switch (io_port) {
  1412. case QXL_IO_UPDATE_AREA:
  1413. {
  1414. QXLCookie *cookie = NULL;
  1415. QXLRect update = d->ram->update_area;
  1416. if (d->ram->update_surface > d->ssd.num_surfaces) {
  1417. qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n",
  1418. d->ram->update_surface);
  1419. break;
  1420. }
  1421. if (update.left >= update.right || update.top >= update.bottom ||
  1422. update.left < 0 || update.top < 0) {
  1423. qxl_set_guest_bug(d,
  1424. "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n",
  1425. update.left, update.top, update.right, update.bottom);
  1426. break;
  1427. }
  1428. if (async == QXL_ASYNC) {
  1429. cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
  1430. QXL_IO_UPDATE_AREA_ASYNC);
  1431. cookie->u.area = update;
  1432. }
  1433. qxl_spice_update_area(d, d->ram->update_surface,
  1434. cookie ? &cookie->u.area : &update,
  1435. NULL, 0, 0, async, cookie);
  1436. break;
  1437. }
  1438. case QXL_IO_NOTIFY_CMD:
  1439. qemu_spice_wakeup(&d->ssd);
  1440. break;
  1441. case QXL_IO_NOTIFY_CURSOR:
  1442. qemu_spice_wakeup(&d->ssd);
  1443. break;
  1444. case QXL_IO_UPDATE_IRQ:
  1445. qxl_update_irq(d);
  1446. break;
  1447. case QXL_IO_NOTIFY_OOM:
  1448. if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
  1449. break;
  1450. }
  1451. d->oom_running = 1;
  1452. qxl_spice_oom(d);
  1453. d->oom_running = 0;
  1454. break;
  1455. case QXL_IO_SET_MODE:
  1456. qxl_set_mode(d, val, 0);
  1457. break;
  1458. case QXL_IO_LOG:
  1459. trace_qxl_io_log(d->id, d->ram->log_buf);
  1460. if (d->guestdebug) {
  1461. fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
  1462. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf);
  1463. }
  1464. break;
  1465. case QXL_IO_RESET:
  1466. qxl_hard_reset(d, 0);
  1467. break;
  1468. case QXL_IO_MEMSLOT_ADD:
  1469. if (val >= NUM_MEMSLOTS) {
  1470. qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range");
  1471. break;
  1472. }
  1473. if (d->guest_slots[val].active) {
  1474. qxl_set_guest_bug(d,
  1475. "QXL_IO_MEMSLOT_ADD: memory slot already active");
  1476. break;
  1477. }
  1478. d->guest_slots[val].slot = d->ram->mem_slot;
  1479. qxl_add_memslot(d, val, 0, async);
  1480. break;
  1481. case QXL_IO_MEMSLOT_DEL:
  1482. if (val >= NUM_MEMSLOTS) {
  1483. qxl_set_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range");
  1484. break;
  1485. }
  1486. qxl_del_memslot(d, val);
  1487. break;
  1488. case QXL_IO_CREATE_PRIMARY:
  1489. if (val != 0) {
  1490. qxl_set_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0",
  1491. async);
  1492. goto cancel_async;
  1493. }
  1494. d->guest_primary.surface = d->ram->create_surface;
  1495. qxl_create_guest_primary(d, 0, async);
  1496. break;
  1497. case QXL_IO_DESTROY_PRIMARY:
  1498. if (val != 0) {
  1499. qxl_set_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0",
  1500. async);
  1501. goto cancel_async;
  1502. }
  1503. if (!qxl_destroy_primary(d, async)) {
  1504. trace_qxl_io_destroy_primary_ignored(d->id,
  1505. qxl_mode_to_string(d->mode));
  1506. goto cancel_async;
  1507. }
  1508. break;
  1509. case QXL_IO_DESTROY_SURFACE_WAIT:
  1510. if (val >= d->ssd.num_surfaces) {
  1511. qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):"
  1512. "%" PRIu64 " >= NUM_SURFACES", async, val);
  1513. goto cancel_async;
  1514. }
  1515. qxl_spice_destroy_surface_wait(d, val, async);
  1516. break;
  1517. case QXL_IO_FLUSH_RELEASE: {
  1518. QXLReleaseRing *ring = &d->ram->release_ring;
  1519. if (ring->prod - ring->cons + 1 == ring->num_items) {
  1520. fprintf(stderr,
  1521. "ERROR: no flush, full release ring [p%d,%dc]\n",
  1522. ring->prod, ring->cons);
  1523. }
  1524. qxl_push_free_res(d, 1 /* flush */);
  1525. break;
  1526. }
  1527. case QXL_IO_FLUSH_SURFACES_ASYNC:
  1528. qxl_spice_flush_surfaces_async(d);
  1529. break;
  1530. case QXL_IO_DESTROY_ALL_SURFACES:
  1531. d->mode = QXL_MODE_UNDEFINED;
  1532. qxl_spice_destroy_surfaces(d, async);
  1533. break;
  1534. case QXL_IO_MONITORS_CONFIG_ASYNC:
  1535. qxl_spice_monitors_config_async(d, 0);
  1536. break;
  1537. default:
  1538. qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port);
  1539. }
  1540. return;
  1541. cancel_async:
  1542. if (async) {
  1543. qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
  1544. qemu_mutex_lock(&d->async_lock);
  1545. d->current_async = QXL_UNDEFINED_IO;
  1546. qemu_mutex_unlock(&d->async_lock);
  1547. }
  1548. }
  1549. static uint64_t ioport_read(void *opaque, hwaddr addr,
  1550. unsigned size)
  1551. {
  1552. PCIQXLDevice *qxl = opaque;
  1553. trace_qxl_io_read_unexpected(qxl->id);
  1554. return 0xff;
  1555. }
  1556. static const MemoryRegionOps qxl_io_ops = {
  1557. .read = ioport_read,
  1558. .write = ioport_write,
  1559. .valid = {
  1560. .min_access_size = 1,
  1561. .max_access_size = 1,
  1562. },
  1563. };
  1564. static void qxl_update_irq_bh(void *opaque)
  1565. {
  1566. PCIQXLDevice *d = opaque;
  1567. qxl_update_irq(d);
  1568. }
  1569. static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
  1570. {
  1571. uint32_t old_pending;
  1572. uint32_t le_events = cpu_to_le32(events);
  1573. trace_qxl_send_events(d->id, events);
  1574. if (!qemu_spice_display_is_running(&d->ssd)) {
  1575. /* spice-server tracks guest running state and should not do this */
  1576. fprintf(stderr, "%s: spice-server bug: guest stopped, ignoring\n",
  1577. __func__);
  1578. trace_qxl_send_events_vm_stopped(d->id, events);
  1579. return;
  1580. }
  1581. old_pending = atomic_fetch_or(&d->ram->int_pending, le_events);
  1582. if ((old_pending & le_events) == le_events) {
  1583. return;
  1584. }
  1585. qemu_bh_schedule(d->update_irq);
  1586. }
  1587. /* graphics console */
  1588. static void qxl_hw_update(void *opaque)
  1589. {
  1590. PCIQXLDevice *qxl = opaque;
  1591. VGACommonState *vga = &qxl->vga;
  1592. switch (qxl->mode) {
  1593. case QXL_MODE_VGA:
  1594. vga->hw_ops->gfx_update(vga);
  1595. break;
  1596. case QXL_MODE_COMPAT:
  1597. case QXL_MODE_NATIVE:
  1598. qxl_render_update(qxl);
  1599. break;
  1600. default:
  1601. break;
  1602. }
  1603. }
  1604. static void qxl_hw_invalidate(void *opaque)
  1605. {
  1606. PCIQXLDevice *qxl = opaque;
  1607. VGACommonState *vga = &qxl->vga;
  1608. if (qxl->mode == QXL_MODE_VGA) {
  1609. vga->hw_ops->invalidate(vga);
  1610. return;
  1611. }
  1612. }
  1613. static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
  1614. {
  1615. PCIQXLDevice *qxl = opaque;
  1616. VGACommonState *vga = &qxl->vga;
  1617. if (qxl->mode == QXL_MODE_VGA) {
  1618. vga->hw_ops->text_update(vga, chardata);
  1619. return;
  1620. }
  1621. }
  1622. static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
  1623. {
  1624. uintptr_t vram_start;
  1625. int i;
  1626. if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
  1627. return;
  1628. }
  1629. /* dirty the primary surface */
  1630. qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
  1631. qxl->shadow_rom.surface0_area_size);
  1632. vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
  1633. /* dirty the off-screen surfaces */
  1634. for (i = 0; i < qxl->ssd.num_surfaces; i++) {
  1635. QXLSurfaceCmd *cmd;
  1636. intptr_t surface_offset;
  1637. int surface_size;
  1638. if (qxl->guest_surfaces.cmds[i] == 0) {
  1639. continue;
  1640. }
  1641. cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i],
  1642. MEMSLOT_GROUP_GUEST);
  1643. assert(cmd);
  1644. assert(cmd->type == QXL_SURFACE_CMD_CREATE);
  1645. surface_offset = (intptr_t)qxl_phys2virt(qxl,
  1646. cmd->u.surface_create.data,
  1647. MEMSLOT_GROUP_GUEST);
  1648. assert(surface_offset);
  1649. surface_offset -= vram_start;
  1650. surface_size = cmd->u.surface_create.height *
  1651. abs(cmd->u.surface_create.stride);
  1652. trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
  1653. qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
  1654. }
  1655. }
  1656. static void qxl_vm_change_state_handler(void *opaque, int running,
  1657. RunState state)
  1658. {
  1659. PCIQXLDevice *qxl = opaque;
  1660. if (running) {
  1661. /*
  1662. * if qxl_send_events was called from spice server context before
  1663. * migration ended, qxl_update_irq for these events might not have been
  1664. * called
  1665. */
  1666. qxl_update_irq(qxl);
  1667. } else {
  1668. /* make sure surfaces are saved before migration */
  1669. qxl_dirty_surfaces(qxl);
  1670. }
  1671. }
  1672. /* display change listener */
  1673. static void display_update(DisplayChangeListener *dcl,
  1674. int x, int y, int w, int h)
  1675. {
  1676. PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
  1677. if (qxl->mode == QXL_MODE_VGA) {
  1678. qemu_spice_display_update(&qxl->ssd, x, y, w, h);
  1679. }
  1680. }
  1681. static void display_switch(DisplayChangeListener *dcl,
  1682. struct DisplaySurface *surface)
  1683. {
  1684. PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
  1685. qxl->ssd.ds = surface;
  1686. if (qxl->mode == QXL_MODE_VGA) {
  1687. qemu_spice_display_switch(&qxl->ssd, surface);
  1688. }
  1689. }
  1690. static void display_refresh(DisplayChangeListener *dcl)
  1691. {
  1692. PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
  1693. if (qxl->mode == QXL_MODE_VGA) {
  1694. qemu_spice_display_refresh(&qxl->ssd);
  1695. } else {
  1696. qemu_mutex_lock(&qxl->ssd.lock);
  1697. qemu_spice_cursor_refresh_unlocked(&qxl->ssd);
  1698. qemu_mutex_unlock(&qxl->ssd.lock);
  1699. }
  1700. }
  1701. static DisplayChangeListenerOps display_listener_ops = {
  1702. .dpy_name = "spice/qxl",
  1703. .dpy_gfx_update = display_update,
  1704. .dpy_gfx_switch = display_switch,
  1705. .dpy_refresh = display_refresh,
  1706. };
  1707. static void qxl_init_ramsize(PCIQXLDevice *qxl)
  1708. {
  1709. /* vga mode framebuffer / primary surface (bar 0, first part) */
  1710. if (qxl->vgamem_size_mb < 8) {
  1711. qxl->vgamem_size_mb = 8;
  1712. }
  1713. qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024;
  1714. /* vga ram (bar 0, total) */
  1715. if (qxl->ram_size_mb != -1) {
  1716. qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024;
  1717. }
  1718. if (qxl->vga.vram_size < qxl->vgamem_size * 2) {
  1719. qxl->vga.vram_size = qxl->vgamem_size * 2;
  1720. }
  1721. /* vram32 (surfaces, 32bit, bar 1) */
  1722. if (qxl->vram32_size_mb != -1) {
  1723. qxl->vram32_size = qxl->vram32_size_mb * 1024 * 1024;
  1724. }
  1725. if (qxl->vram32_size < 4096) {
  1726. qxl->vram32_size = 4096;
  1727. }
  1728. /* vram (surfaces, 64bit, bar 4+5) */
  1729. if (qxl->vram_size_mb != -1) {
  1730. qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
  1731. }
  1732. if (qxl->vram_size < qxl->vram32_size) {
  1733. qxl->vram_size = qxl->vram32_size;
  1734. }
  1735. if (qxl->revision == 1) {
  1736. qxl->vram32_size = 4096;
  1737. qxl->vram_size = 4096;
  1738. }
  1739. qxl->vgamem_size = msb_mask(qxl->vgamem_size * 2 - 1);
  1740. qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
  1741. qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1);
  1742. qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
  1743. }
  1744. static int qxl_init_common(PCIQXLDevice *qxl)
  1745. {
  1746. uint8_t* config = qxl->pci.config;
  1747. uint32_t pci_device_rev;
  1748. uint32_t io_size;
  1749. qxl->mode = QXL_MODE_UNDEFINED;
  1750. qxl->generation = 1;
  1751. qxl->num_memslots = NUM_MEMSLOTS;
  1752. qemu_mutex_init(&qxl->track_lock);
  1753. qemu_mutex_init(&qxl->async_lock);
  1754. qxl->current_async = QXL_UNDEFINED_IO;
  1755. qxl->guest_bug = 0;
  1756. switch (qxl->revision) {
  1757. case 1: /* spice 0.4 -- qxl-1 */
  1758. pci_device_rev = QXL_REVISION_STABLE_V04;
  1759. io_size = 8;
  1760. break;
  1761. case 2: /* spice 0.6 -- qxl-2 */
  1762. pci_device_rev = QXL_REVISION_STABLE_V06;
  1763. io_size = 16;
  1764. break;
  1765. case 3: /* qxl-3 */
  1766. pci_device_rev = QXL_REVISION_STABLE_V10;
  1767. io_size = 32; /* PCI region size must be pow2 */
  1768. break;
  1769. case 4: /* qxl-4 */
  1770. pci_device_rev = QXL_REVISION_STABLE_V12;
  1771. io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
  1772. break;
  1773. default:
  1774. error_report("Invalid revision %d for qxl device (max %d)",
  1775. qxl->revision, QXL_DEFAULT_REVISION);
  1776. return -1;
  1777. }
  1778. pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
  1779. pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
  1780. qxl->rom_size = qxl_rom_size();
  1781. memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom",
  1782. qxl->rom_size);
  1783. vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
  1784. init_qxl_rom(qxl);
  1785. init_qxl_ram(qxl);
  1786. qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces);
  1787. memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram",
  1788. qxl->vram_size);
  1789. vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
  1790. memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32",
  1791. &qxl->vram_bar, 0, qxl->vram32_size);
  1792. memory_region_init_io(&qxl->io_bar, OBJECT(qxl), &qxl_io_ops, qxl,
  1793. "qxl-ioports", io_size);
  1794. if (qxl->id == 0) {
  1795. vga_dirty_log_start(&qxl->vga);
  1796. }
  1797. memory_region_set_flush_coalesced(&qxl->io_bar);
  1798. pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
  1799. PCI_BASE_ADDRESS_SPACE_IO, &qxl->io_bar);
  1800. pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
  1801. PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->rom_bar);
  1802. pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
  1803. PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vga.vram);
  1804. pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX,
  1805. PCI_BASE_ADDRESS_SPACE_MEMORY, &qxl->vram32_bar);
  1806. if (qxl->vram32_size < qxl->vram_size) {
  1807. /*
  1808. * Make the 64bit vram bar show up only in case it is
  1809. * configured to be larger than the 32bit vram bar.
  1810. */
  1811. pci_register_bar(&qxl->pci, QXL_VRAM64_RANGE_INDEX,
  1812. PCI_BASE_ADDRESS_SPACE_MEMORY |
  1813. PCI_BASE_ADDRESS_MEM_TYPE_64 |
  1814. PCI_BASE_ADDRESS_MEM_PREFETCH,
  1815. &qxl->vram_bar);
  1816. }
  1817. /* print pci bar details */
  1818. dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
  1819. qxl->id == 0 ? "pri" : "sec",
  1820. qxl->vga.vram_size / (1024*1024));
  1821. dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
  1822. qxl->vram32_size / (1024*1024));
  1823. dprint(qxl, 1, "vram/64: %d MB %s\n",
  1824. qxl->vram_size / (1024*1024),
  1825. qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
  1826. qxl->ssd.qxl.base.sif = &qxl_interface.base;
  1827. if (qemu_spice_add_display_interface(&qxl->ssd.qxl, qxl->vga.con) != 0) {
  1828. error_report("qxl interface %d.%d not supported by spice-server",
  1829. SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
  1830. return -1;
  1831. }
  1832. qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
  1833. qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
  1834. qxl_reset_state(qxl);
  1835. qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
  1836. return 0;
  1837. }
  1838. static const GraphicHwOps qxl_ops = {
  1839. .invalidate = qxl_hw_invalidate,
  1840. .gfx_update = qxl_hw_update,
  1841. .text_update = qxl_hw_text_update,
  1842. };
  1843. static int qxl_init_primary(PCIDevice *dev)
  1844. {
  1845. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
  1846. VGACommonState *vga = &qxl->vga;
  1847. int rc;
  1848. qxl->id = 0;
  1849. qxl_init_ramsize(qxl);
  1850. vga->vbe_size = qxl->vgamem_size;
  1851. vga->vram_size_mb = qxl->vga.vram_size >> 20;
  1852. vga_common_init(vga, OBJECT(dev), true);
  1853. vga_init(vga, OBJECT(dev),
  1854. pci_address_space(dev), pci_address_space_io(dev), false);
  1855. portio_list_init(&qxl->vga_port_list, OBJECT(dev), qxl_vga_portio_list,
  1856. vga, "vga");
  1857. portio_list_set_flush_coalesced(&qxl->vga_port_list);
  1858. portio_list_add(&qxl->vga_port_list, pci_address_space_io(dev), 0x3b0);
  1859. vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
  1860. qemu_spice_display_init_common(&qxl->ssd);
  1861. rc = qxl_init_common(qxl);
  1862. if (rc != 0) {
  1863. return rc;
  1864. }
  1865. qxl->ssd.dcl.ops = &display_listener_ops;
  1866. qxl->ssd.dcl.con = vga->con;
  1867. register_displaychangelistener(&qxl->ssd.dcl);
  1868. return rc;
  1869. }
  1870. static int qxl_init_secondary(PCIDevice *dev)
  1871. {
  1872. static int device_id = 1;
  1873. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
  1874. qxl->id = device_id++;
  1875. qxl_init_ramsize(qxl);
  1876. memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram",
  1877. qxl->vga.vram_size);
  1878. vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
  1879. qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
  1880. qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
  1881. return qxl_init_common(qxl);
  1882. }
  1883. static void qxl_pre_save(void *opaque)
  1884. {
  1885. PCIQXLDevice* d = opaque;
  1886. uint8_t *ram_start = d->vga.vram_ptr;
  1887. trace_qxl_pre_save(d->id);
  1888. if (d->last_release == NULL) {
  1889. d->last_release_offset = 0;
  1890. } else {
  1891. d->last_release_offset = (uint8_t *)d->last_release - ram_start;
  1892. }
  1893. assert(d->last_release_offset < d->vga.vram_size);
  1894. }
  1895. static int qxl_pre_load(void *opaque)
  1896. {
  1897. PCIQXLDevice* d = opaque;
  1898. trace_qxl_pre_load(d->id);
  1899. qxl_hard_reset(d, 1);
  1900. qxl_exit_vga_mode(d);
  1901. return 0;
  1902. }
  1903. static void qxl_create_memslots(PCIQXLDevice *d)
  1904. {
  1905. int i;
  1906. for (i = 0; i < NUM_MEMSLOTS; i++) {
  1907. if (!d->guest_slots[i].active) {
  1908. continue;
  1909. }
  1910. qxl_add_memslot(d, i, 0, QXL_SYNC);
  1911. }
  1912. }
  1913. static int qxl_post_load(void *opaque, int version)
  1914. {
  1915. PCIQXLDevice* d = opaque;
  1916. uint8_t *ram_start = d->vga.vram_ptr;
  1917. QXLCommandExt *cmds;
  1918. int in, out, newmode;
  1919. assert(d->last_release_offset < d->vga.vram_size);
  1920. if (d->last_release_offset == 0) {
  1921. d->last_release = NULL;
  1922. } else {
  1923. d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
  1924. }
  1925. d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
  1926. trace_qxl_post_load(d->id, qxl_mode_to_string(d->mode));
  1927. newmode = d->mode;
  1928. d->mode = QXL_MODE_UNDEFINED;
  1929. switch (newmode) {
  1930. case QXL_MODE_UNDEFINED:
  1931. qxl_create_memslots(d);
  1932. break;
  1933. case QXL_MODE_VGA:
  1934. qxl_create_memslots(d);
  1935. qxl_enter_vga_mode(d);
  1936. break;
  1937. case QXL_MODE_NATIVE:
  1938. qxl_create_memslots(d);
  1939. qxl_create_guest_primary(d, 1, QXL_SYNC);
  1940. /* replay surface-create and cursor-set commands */
  1941. cmds = g_malloc0(sizeof(QXLCommandExt) * (d->ssd.num_surfaces + 1));
  1942. for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) {
  1943. if (d->guest_surfaces.cmds[in] == 0) {
  1944. continue;
  1945. }
  1946. cmds[out].cmd.data = d->guest_surfaces.cmds[in];
  1947. cmds[out].cmd.type = QXL_CMD_SURFACE;
  1948. cmds[out].group_id = MEMSLOT_GROUP_GUEST;
  1949. out++;
  1950. }
  1951. if (d->guest_cursor) {
  1952. cmds[out].cmd.data = d->guest_cursor;
  1953. cmds[out].cmd.type = QXL_CMD_CURSOR;
  1954. cmds[out].group_id = MEMSLOT_GROUP_GUEST;
  1955. out++;
  1956. }
  1957. qxl_spice_loadvm_commands(d, cmds, out);
  1958. g_free(cmds);
  1959. if (d->guest_monitors_config) {
  1960. qxl_spice_monitors_config_async(d, 1);
  1961. }
  1962. break;
  1963. case QXL_MODE_COMPAT:
  1964. /* note: no need to call qxl_create_memslots, qxl_set_mode
  1965. * creates the mem slot. */
  1966. qxl_set_mode(d, d->shadow_rom.mode, 1);
  1967. break;
  1968. }
  1969. return 0;
  1970. }
  1971. #define QXL_SAVE_VERSION 21
  1972. static bool qxl_monitors_config_needed(void *opaque)
  1973. {
  1974. PCIQXLDevice *qxl = opaque;
  1975. return qxl->guest_monitors_config != 0;
  1976. }
  1977. static VMStateDescription qxl_memslot = {
  1978. .name = "qxl-memslot",
  1979. .version_id = QXL_SAVE_VERSION,
  1980. .minimum_version_id = QXL_SAVE_VERSION,
  1981. .fields = (VMStateField[]) {
  1982. VMSTATE_UINT64(slot.mem_start, struct guest_slots),
  1983. VMSTATE_UINT64(slot.mem_end, struct guest_slots),
  1984. VMSTATE_UINT32(active, struct guest_slots),
  1985. VMSTATE_END_OF_LIST()
  1986. }
  1987. };
  1988. static VMStateDescription qxl_surface = {
  1989. .name = "qxl-surface",
  1990. .version_id = QXL_SAVE_VERSION,
  1991. .minimum_version_id = QXL_SAVE_VERSION,
  1992. .fields = (VMStateField[]) {
  1993. VMSTATE_UINT32(width, QXLSurfaceCreate),
  1994. VMSTATE_UINT32(height, QXLSurfaceCreate),
  1995. VMSTATE_INT32(stride, QXLSurfaceCreate),
  1996. VMSTATE_UINT32(format, QXLSurfaceCreate),
  1997. VMSTATE_UINT32(position, QXLSurfaceCreate),
  1998. VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate),
  1999. VMSTATE_UINT32(flags, QXLSurfaceCreate),
  2000. VMSTATE_UINT32(type, QXLSurfaceCreate),
  2001. VMSTATE_UINT64(mem, QXLSurfaceCreate),
  2002. VMSTATE_END_OF_LIST()
  2003. }
  2004. };
  2005. static VMStateDescription qxl_vmstate_monitors_config = {
  2006. .name = "qxl/monitors-config",
  2007. .version_id = 1,
  2008. .minimum_version_id = 1,
  2009. .fields = (VMStateField[]) {
  2010. VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
  2011. VMSTATE_END_OF_LIST()
  2012. },
  2013. };
  2014. static VMStateDescription qxl_vmstate = {
  2015. .name = "qxl",
  2016. .version_id = QXL_SAVE_VERSION,
  2017. .minimum_version_id = QXL_SAVE_VERSION,
  2018. .pre_save = qxl_pre_save,
  2019. .pre_load = qxl_pre_load,
  2020. .post_load = qxl_post_load,
  2021. .fields = (VMStateField[]) {
  2022. VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
  2023. VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
  2024. VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
  2025. VMSTATE_UINT32(num_free_res, PCIQXLDevice),
  2026. VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
  2027. VMSTATE_UINT32(mode, PCIQXLDevice),
  2028. VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
  2029. VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
  2030. VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
  2031. qxl_memslot, struct guest_slots),
  2032. VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
  2033. qxl_surface, QXLSurfaceCreate),
  2034. VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice),
  2035. VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice,
  2036. ssd.num_surfaces, 0,
  2037. vmstate_info_uint64, uint64_t),
  2038. VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
  2039. VMSTATE_END_OF_LIST()
  2040. },
  2041. .subsections = (VMStateSubsection[]) {
  2042. {
  2043. .vmsd = &qxl_vmstate_monitors_config,
  2044. .needed = qxl_monitors_config_needed,
  2045. }, {
  2046. /* empty */
  2047. }
  2048. }
  2049. };
  2050. static Property qxl_properties[] = {
  2051. DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
  2052. 64 * 1024 * 1024),
  2053. DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
  2054. 64 * 1024 * 1024),
  2055. DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
  2056. QXL_DEFAULT_REVISION),
  2057. DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
  2058. DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
  2059. DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
  2060. DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
  2061. DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1),
  2062. DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
  2063. DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
  2064. DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
  2065. DEFINE_PROP_END_OF_LIST(),
  2066. };
  2067. static void qxl_primary_class_init(ObjectClass *klass, void *data)
  2068. {
  2069. DeviceClass *dc = DEVICE_CLASS(klass);
  2070. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  2071. k->init = qxl_init_primary;
  2072. k->romfile = "vgabios-qxl.bin";
  2073. k->vendor_id = REDHAT_PCI_VENDOR_ID;
  2074. k->device_id = QXL_DEVICE_ID_STABLE;
  2075. k->class_id = PCI_CLASS_DISPLAY_VGA;
  2076. set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
  2077. dc->desc = "Spice QXL GPU (primary, vga compatible)";
  2078. dc->reset = qxl_reset_handler;
  2079. dc->vmsd = &qxl_vmstate;
  2080. dc->props = qxl_properties;
  2081. dc->hotpluggable = false;
  2082. }
  2083. static const TypeInfo qxl_primary_info = {
  2084. .name = "qxl-vga",
  2085. .parent = TYPE_PCI_DEVICE,
  2086. .instance_size = sizeof(PCIQXLDevice),
  2087. .class_init = qxl_primary_class_init,
  2088. };
  2089. static void qxl_secondary_class_init(ObjectClass *klass, void *data)
  2090. {
  2091. DeviceClass *dc = DEVICE_CLASS(klass);
  2092. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  2093. k->init = qxl_init_secondary;
  2094. k->vendor_id = REDHAT_PCI_VENDOR_ID;
  2095. k->device_id = QXL_DEVICE_ID_STABLE;
  2096. k->class_id = PCI_CLASS_DISPLAY_OTHER;
  2097. set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
  2098. dc->desc = "Spice QXL GPU (secondary)";
  2099. dc->reset = qxl_reset_handler;
  2100. dc->vmsd = &qxl_vmstate;
  2101. dc->props = qxl_properties;
  2102. }
  2103. static const TypeInfo qxl_secondary_info = {
  2104. .name = "qxl",
  2105. .parent = TYPE_PCI_DEVICE,
  2106. .instance_size = sizeof(PCIQXLDevice),
  2107. .class_init = qxl_secondary_class_init,
  2108. };
  2109. static void qxl_register_types(void)
  2110. {
  2111. type_register_static(&qxl_primary_info);
  2112. type_register_static(&qxl_secondary_info);
  2113. }
  2114. type_init(qxl_register_types)