qxl.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551
  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 <pthread.h>
  21. #include "qemu-common.h"
  22. #include "qemu-timer.h"
  23. #include "qemu-queue.h"
  24. #include "monitor.h"
  25. #include "sysemu.h"
  26. #include "qxl.h"
  27. #undef SPICE_RING_PROD_ITEM
  28. #define SPICE_RING_PROD_ITEM(r, ret) { \
  29. typeof(r) start = r; \
  30. typeof(r) end = r + 1; \
  31. uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
  32. typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
  33. if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
  34. abort(); \
  35. } \
  36. ret = &m_item->el; \
  37. }
  38. #undef SPICE_RING_CONS_ITEM
  39. #define SPICE_RING_CONS_ITEM(r, ret) { \
  40. typeof(r) start = r; \
  41. typeof(r) end = r + 1; \
  42. uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
  43. typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
  44. if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
  45. abort(); \
  46. } \
  47. ret = &m_item->el; \
  48. }
  49. #undef ALIGN
  50. #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
  51. #define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9"
  52. #define QXL_MODE(_x, _y, _b, _o) \
  53. { .x_res = _x, \
  54. .y_res = _y, \
  55. .bits = _b, \
  56. .stride = (_x) * (_b) / 8, \
  57. .x_mili = PIXEL_SIZE * (_x), \
  58. .y_mili = PIXEL_SIZE * (_y), \
  59. .orientation = _o, \
  60. }
  61. #define QXL_MODE_16_32(x_res, y_res, orientation) \
  62. QXL_MODE(x_res, y_res, 16, orientation), \
  63. QXL_MODE(x_res, y_res, 32, orientation)
  64. #define QXL_MODE_EX(x_res, y_res) \
  65. QXL_MODE_16_32(x_res, y_res, 0), \
  66. QXL_MODE_16_32(y_res, x_res, 1), \
  67. QXL_MODE_16_32(x_res, y_res, 2), \
  68. QXL_MODE_16_32(y_res, x_res, 3)
  69. static QXLMode qxl_modes[] = {
  70. QXL_MODE_EX(640, 480),
  71. QXL_MODE_EX(800, 480),
  72. QXL_MODE_EX(800, 600),
  73. QXL_MODE_EX(832, 624),
  74. QXL_MODE_EX(960, 640),
  75. QXL_MODE_EX(1024, 600),
  76. QXL_MODE_EX(1024, 768),
  77. QXL_MODE_EX(1152, 864),
  78. QXL_MODE_EX(1152, 870),
  79. QXL_MODE_EX(1280, 720),
  80. QXL_MODE_EX(1280, 760),
  81. QXL_MODE_EX(1280, 768),
  82. QXL_MODE_EX(1280, 800),
  83. QXL_MODE_EX(1280, 960),
  84. QXL_MODE_EX(1280, 1024),
  85. QXL_MODE_EX(1360, 768),
  86. QXL_MODE_EX(1366, 768),
  87. QXL_MODE_EX(1400, 1050),
  88. QXL_MODE_EX(1440, 900),
  89. QXL_MODE_EX(1600, 900),
  90. QXL_MODE_EX(1600, 1200),
  91. QXL_MODE_EX(1680, 1050),
  92. QXL_MODE_EX(1920, 1080),
  93. #if VGA_RAM_SIZE >= (16 * 1024 * 1024)
  94. /* these modes need more than 8 MB video memory */
  95. QXL_MODE_EX(1920, 1200),
  96. QXL_MODE_EX(1920, 1440),
  97. QXL_MODE_EX(2048, 1536),
  98. QXL_MODE_EX(2560, 1440),
  99. QXL_MODE_EX(2560, 1600),
  100. #endif
  101. #if VGA_RAM_SIZE >= (32 * 1024 * 1024)
  102. /* these modes need more than 16 MB video memory */
  103. QXL_MODE_EX(2560, 2048),
  104. QXL_MODE_EX(2800, 2100),
  105. QXL_MODE_EX(3200, 2400),
  106. #endif
  107. };
  108. static PCIQXLDevice *qxl0;
  109. static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
  110. static void qxl_destroy_primary(PCIQXLDevice *d);
  111. static void qxl_reset_memslots(PCIQXLDevice *d);
  112. static void qxl_reset_surfaces(PCIQXLDevice *d);
  113. static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
  114. static inline uint32_t msb_mask(uint32_t val)
  115. {
  116. uint32_t mask;
  117. do {
  118. mask = ~(val - 1) & val;
  119. val &= ~mask;
  120. } while (mask < val);
  121. return mask;
  122. }
  123. static ram_addr_t qxl_rom_size(void)
  124. {
  125. uint32_t rom_size = sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes);
  126. rom_size = MAX(rom_size, TARGET_PAGE_SIZE);
  127. rom_size = msb_mask(rom_size * 2 - 1);
  128. return rom_size;
  129. }
  130. static void init_qxl_rom(PCIQXLDevice *d)
  131. {
  132. QXLRom *rom = qemu_get_ram_ptr(d->rom_offset);
  133. QXLModes *modes = (QXLModes *)(rom + 1);
  134. uint32_t ram_header_size;
  135. uint32_t surface0_area_size;
  136. uint32_t num_pages;
  137. uint32_t fb, maxfb = 0;
  138. int i;
  139. memset(rom, 0, d->rom_size);
  140. rom->magic = cpu_to_le32(QXL_ROM_MAGIC);
  141. rom->id = cpu_to_le32(d->id);
  142. rom->log_level = cpu_to_le32(d->guestdebug);
  143. rom->modes_offset = cpu_to_le32(sizeof(QXLRom));
  144. rom->slot_gen_bits = MEMSLOT_GENERATION_BITS;
  145. rom->slot_id_bits = MEMSLOT_SLOT_BITS;
  146. rom->slots_start = 1;
  147. rom->slots_end = NUM_MEMSLOTS - 1;
  148. rom->n_surfaces = cpu_to_le32(NUM_SURFACES);
  149. modes->n_modes = cpu_to_le32(ARRAY_SIZE(qxl_modes));
  150. for (i = 0; i < modes->n_modes; i++) {
  151. fb = qxl_modes[i].y_res * qxl_modes[i].stride;
  152. if (maxfb < fb) {
  153. maxfb = fb;
  154. }
  155. modes->modes[i].id = cpu_to_le32(i);
  156. modes->modes[i].x_res = cpu_to_le32(qxl_modes[i].x_res);
  157. modes->modes[i].y_res = cpu_to_le32(qxl_modes[i].y_res);
  158. modes->modes[i].bits = cpu_to_le32(qxl_modes[i].bits);
  159. modes->modes[i].stride = cpu_to_le32(qxl_modes[i].stride);
  160. modes->modes[i].x_mili = cpu_to_le32(qxl_modes[i].x_mili);
  161. modes->modes[i].y_mili = cpu_to_le32(qxl_modes[i].y_mili);
  162. modes->modes[i].orientation = cpu_to_le32(qxl_modes[i].orientation);
  163. }
  164. if (maxfb < VGA_RAM_SIZE && d->id == 0)
  165. maxfb = VGA_RAM_SIZE;
  166. ram_header_size = ALIGN(sizeof(QXLRam), 4096);
  167. surface0_area_size = ALIGN(maxfb, 4096);
  168. num_pages = d->vga.vram_size;
  169. num_pages -= ram_header_size;
  170. num_pages -= surface0_area_size;
  171. num_pages = num_pages / TARGET_PAGE_SIZE;
  172. rom->draw_area_offset = cpu_to_le32(0);
  173. rom->surface0_area_size = cpu_to_le32(surface0_area_size);
  174. rom->pages_offset = cpu_to_le32(surface0_area_size);
  175. rom->num_pages = cpu_to_le32(num_pages);
  176. rom->ram_header_offset = cpu_to_le32(d->vga.vram_size - ram_header_size);
  177. d->shadow_rom = *rom;
  178. d->rom = rom;
  179. d->modes = modes;
  180. }
  181. static void init_qxl_ram(PCIQXLDevice *d)
  182. {
  183. uint8_t *buf;
  184. uint64_t *item;
  185. buf = d->vga.vram_ptr;
  186. d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
  187. d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC);
  188. d->ram->int_pending = cpu_to_le32(0);
  189. d->ram->int_mask = cpu_to_le32(0);
  190. SPICE_RING_INIT(&d->ram->cmd_ring);
  191. SPICE_RING_INIT(&d->ram->cursor_ring);
  192. SPICE_RING_INIT(&d->ram->release_ring);
  193. SPICE_RING_PROD_ITEM(&d->ram->release_ring, item);
  194. *item = 0;
  195. qxl_ring_set_dirty(d);
  196. }
  197. /* can be called from spice server thread context */
  198. static void qxl_set_dirty(ram_addr_t addr, ram_addr_t end)
  199. {
  200. while (addr < end) {
  201. cpu_physical_memory_set_dirty(addr);
  202. addr += TARGET_PAGE_SIZE;
  203. }
  204. }
  205. static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
  206. {
  207. ram_addr_t addr = qxl->rom_offset;
  208. qxl_set_dirty(addr, addr + qxl->rom_size);
  209. }
  210. /* called from spice server thread context only */
  211. static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
  212. {
  213. ram_addr_t addr = qxl->vga.vram_offset;
  214. void *base = qxl->vga.vram_ptr;
  215. intptr_t offset;
  216. offset = ptr - base;
  217. offset &= ~(TARGET_PAGE_SIZE-1);
  218. assert(offset < qxl->vga.vram_size);
  219. qxl_set_dirty(addr + offset, addr + offset + TARGET_PAGE_SIZE);
  220. }
  221. /* can be called from spice server thread context */
  222. static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
  223. {
  224. ram_addr_t addr = qxl->vga.vram_offset + qxl->shadow_rom.ram_header_offset;
  225. ram_addr_t end = qxl->vga.vram_offset + qxl->vga.vram_size;
  226. qxl_set_dirty(addr, end);
  227. }
  228. /*
  229. * keep track of some command state, for savevm/loadvm.
  230. * called from spice server thread context only
  231. */
  232. static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
  233. {
  234. switch (le32_to_cpu(ext->cmd.type)) {
  235. case QXL_CMD_SURFACE:
  236. {
  237. QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
  238. uint32_t id = le32_to_cpu(cmd->surface_id);
  239. PANIC_ON(id >= NUM_SURFACES);
  240. if (cmd->type == QXL_SURFACE_CMD_CREATE) {
  241. qxl->guest_surfaces.cmds[id] = ext->cmd.data;
  242. qxl->guest_surfaces.count++;
  243. if (qxl->guest_surfaces.max < qxl->guest_surfaces.count)
  244. qxl->guest_surfaces.max = qxl->guest_surfaces.count;
  245. }
  246. if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
  247. qxl->guest_surfaces.cmds[id] = 0;
  248. qxl->guest_surfaces.count--;
  249. }
  250. break;
  251. }
  252. case QXL_CMD_CURSOR:
  253. {
  254. QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
  255. if (cmd->type == QXL_CURSOR_SET) {
  256. qxl->guest_cursor = ext->cmd.data;
  257. }
  258. break;
  259. }
  260. }
  261. }
  262. /* spice display interface callbacks */
  263. static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
  264. {
  265. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  266. dprint(qxl, 1, "%s:\n", __FUNCTION__);
  267. qxl->ssd.worker = qxl_worker;
  268. }
  269. static void interface_set_compression_level(QXLInstance *sin, int level)
  270. {
  271. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  272. dprint(qxl, 1, "%s: %d\n", __FUNCTION__, level);
  273. qxl->shadow_rom.compression_level = cpu_to_le32(level);
  274. qxl->rom->compression_level = cpu_to_le32(level);
  275. qxl_rom_set_dirty(qxl);
  276. }
  277. static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
  278. {
  279. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  280. qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
  281. qxl->rom->mm_clock = cpu_to_le32(mm_time);
  282. qxl_rom_set_dirty(qxl);
  283. }
  284. static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
  285. {
  286. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  287. dprint(qxl, 1, "%s:\n", __FUNCTION__);
  288. info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
  289. info->memslot_id_bits = MEMSLOT_SLOT_BITS;
  290. info->num_memslots = NUM_MEMSLOTS;
  291. info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
  292. info->internal_groupslot_id = 0;
  293. info->qxl_ram_size = le32_to_cpu(qxl->shadow_rom.num_pages) << TARGET_PAGE_BITS;
  294. info->n_surfaces = NUM_SURFACES;
  295. }
  296. static const char *qxl_mode_to_string(int mode)
  297. {
  298. switch (mode) {
  299. case QXL_MODE_COMPAT:
  300. return "compat";
  301. case QXL_MODE_NATIVE:
  302. return "native";
  303. case QXL_MODE_UNDEFINED:
  304. return "undefined";
  305. case QXL_MODE_VGA:
  306. return "vga";
  307. }
  308. return "INVALID";
  309. }
  310. /* called from spice server thread context only */
  311. static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
  312. {
  313. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  314. SimpleSpiceUpdate *update;
  315. QXLCommandRing *ring;
  316. QXLCommand *cmd;
  317. int notify, ret;
  318. switch (qxl->mode) {
  319. case QXL_MODE_VGA:
  320. dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
  321. ret = false;
  322. qemu_mutex_lock(&qxl->ssd.lock);
  323. if (qxl->ssd.update != NULL) {
  324. update = qxl->ssd.update;
  325. qxl->ssd.update = NULL;
  326. *ext = update->ext;
  327. ret = true;
  328. }
  329. qemu_mutex_unlock(&qxl->ssd.lock);
  330. if (ret) {
  331. dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
  332. qxl_log_command(qxl, "vga", ext);
  333. }
  334. return ret;
  335. case QXL_MODE_COMPAT:
  336. case QXL_MODE_NATIVE:
  337. case QXL_MODE_UNDEFINED:
  338. dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
  339. ring = &qxl->ram->cmd_ring;
  340. if (SPICE_RING_IS_EMPTY(ring)) {
  341. return false;
  342. }
  343. dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
  344. SPICE_RING_CONS_ITEM(ring, cmd);
  345. ext->cmd = *cmd;
  346. ext->group_id = MEMSLOT_GROUP_GUEST;
  347. ext->flags = qxl->cmdflags;
  348. SPICE_RING_POP(ring, notify);
  349. qxl_ring_set_dirty(qxl);
  350. if (notify) {
  351. qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY);
  352. }
  353. qxl->guest_primary.commands++;
  354. qxl_track_command(qxl, ext);
  355. qxl_log_command(qxl, "cmd", ext);
  356. return true;
  357. default:
  358. return false;
  359. }
  360. }
  361. /* called from spice server thread context only */
  362. static int interface_req_cmd_notification(QXLInstance *sin)
  363. {
  364. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  365. int wait = 1;
  366. switch (qxl->mode) {
  367. case QXL_MODE_COMPAT:
  368. case QXL_MODE_NATIVE:
  369. case QXL_MODE_UNDEFINED:
  370. SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait);
  371. qxl_ring_set_dirty(qxl);
  372. break;
  373. default:
  374. /* nothing */
  375. break;
  376. }
  377. return wait;
  378. }
  379. /* called from spice server thread context only */
  380. static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
  381. {
  382. QXLReleaseRing *ring = &d->ram->release_ring;
  383. uint64_t *item;
  384. int notify;
  385. #define QXL_FREE_BUNCH_SIZE 32
  386. if (ring->prod - ring->cons + 1 == ring->num_items) {
  387. /* ring full -- can't push */
  388. return;
  389. }
  390. if (!flush && d->oom_running) {
  391. /* collect everything from oom handler before pushing */
  392. return;
  393. }
  394. if (!flush && d->num_free_res < QXL_FREE_BUNCH_SIZE) {
  395. /* collect a bit more before pushing */
  396. return;
  397. }
  398. SPICE_RING_PUSH(ring, notify);
  399. dprint(d, 2, "free: push %d items, notify %s, ring %d/%d [%d,%d]\n",
  400. d->num_free_res, notify ? "yes" : "no",
  401. ring->prod - ring->cons, ring->num_items,
  402. ring->prod, ring->cons);
  403. if (notify) {
  404. qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
  405. }
  406. SPICE_RING_PROD_ITEM(ring, item);
  407. *item = 0;
  408. d->num_free_res = 0;
  409. d->last_release = NULL;
  410. qxl_ring_set_dirty(d);
  411. }
  412. /* called from spice server thread context only */
  413. static void interface_release_resource(QXLInstance *sin,
  414. struct QXLReleaseInfoExt ext)
  415. {
  416. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  417. QXLReleaseRing *ring;
  418. uint64_t *item, id;
  419. if (ext.group_id == MEMSLOT_GROUP_HOST) {
  420. /* host group -> vga mode update request */
  421. qemu_spice_destroy_update(&qxl->ssd, (void*)ext.info->id);
  422. return;
  423. }
  424. /*
  425. * ext->info points into guest-visible memory
  426. * pci bar 0, $command.release_info
  427. */
  428. ring = &qxl->ram->release_ring;
  429. SPICE_RING_PROD_ITEM(ring, item);
  430. if (*item == 0) {
  431. /* stick head into the ring */
  432. id = ext.info->id;
  433. ext.info->next = 0;
  434. qxl_ram_set_dirty(qxl, &ext.info->next);
  435. *item = id;
  436. qxl_ring_set_dirty(qxl);
  437. } else {
  438. /* append item to the list */
  439. qxl->last_release->next = ext.info->id;
  440. qxl_ram_set_dirty(qxl, &qxl->last_release->next);
  441. ext.info->next = 0;
  442. qxl_ram_set_dirty(qxl, &ext.info->next);
  443. }
  444. qxl->last_release = ext.info;
  445. qxl->num_free_res++;
  446. dprint(qxl, 3, "%4d\r", qxl->num_free_res);
  447. qxl_push_free_res(qxl, 0);
  448. }
  449. /* called from spice server thread context only */
  450. static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
  451. {
  452. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  453. QXLCursorRing *ring;
  454. QXLCommand *cmd;
  455. int notify;
  456. switch (qxl->mode) {
  457. case QXL_MODE_COMPAT:
  458. case QXL_MODE_NATIVE:
  459. case QXL_MODE_UNDEFINED:
  460. ring = &qxl->ram->cursor_ring;
  461. if (SPICE_RING_IS_EMPTY(ring)) {
  462. return false;
  463. }
  464. SPICE_RING_CONS_ITEM(ring, cmd);
  465. ext->cmd = *cmd;
  466. ext->group_id = MEMSLOT_GROUP_GUEST;
  467. ext->flags = qxl->cmdflags;
  468. SPICE_RING_POP(ring, notify);
  469. qxl_ring_set_dirty(qxl);
  470. if (notify) {
  471. qxl_send_events(qxl, QXL_INTERRUPT_CURSOR);
  472. }
  473. qxl->guest_primary.commands++;
  474. qxl_track_command(qxl, ext);
  475. qxl_log_command(qxl, "csr", ext);
  476. if (qxl->id == 0) {
  477. qxl_render_cursor(qxl, ext);
  478. }
  479. return true;
  480. default:
  481. return false;
  482. }
  483. }
  484. /* called from spice server thread context only */
  485. static int interface_req_cursor_notification(QXLInstance *sin)
  486. {
  487. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  488. int wait = 1;
  489. switch (qxl->mode) {
  490. case QXL_MODE_COMPAT:
  491. case QXL_MODE_NATIVE:
  492. case QXL_MODE_UNDEFINED:
  493. SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait);
  494. qxl_ring_set_dirty(qxl);
  495. break;
  496. default:
  497. /* nothing */
  498. break;
  499. }
  500. return wait;
  501. }
  502. /* called from spice server thread context */
  503. static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
  504. {
  505. fprintf(stderr, "%s: abort()\n", __FUNCTION__);
  506. abort();
  507. }
  508. /* called from spice server thread context only */
  509. static int interface_flush_resources(QXLInstance *sin)
  510. {
  511. PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
  512. int ret;
  513. dprint(qxl, 1, "free: guest flush (have %d)\n", qxl->num_free_res);
  514. ret = qxl->num_free_res;
  515. if (ret) {
  516. qxl_push_free_res(qxl, 1);
  517. }
  518. return ret;
  519. }
  520. static const QXLInterface qxl_interface = {
  521. .base.type = SPICE_INTERFACE_QXL,
  522. .base.description = "qxl gpu",
  523. .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
  524. .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
  525. .attache_worker = interface_attach_worker,
  526. .set_compression_level = interface_set_compression_level,
  527. .set_mm_time = interface_set_mm_time,
  528. .get_init_info = interface_get_init_info,
  529. /* the callbacks below are called from spice server thread context */
  530. .get_command = interface_get_command,
  531. .req_cmd_notification = interface_req_cmd_notification,
  532. .release_resource = interface_release_resource,
  533. .get_cursor_command = interface_get_cursor_command,
  534. .req_cursor_notification = interface_req_cursor_notification,
  535. .notify_update = interface_notify_update,
  536. .flush_resources = interface_flush_resources,
  537. };
  538. static void qxl_enter_vga_mode(PCIQXLDevice *d)
  539. {
  540. if (d->mode == QXL_MODE_VGA) {
  541. return;
  542. }
  543. dprint(d, 1, "%s\n", __FUNCTION__);
  544. qemu_spice_create_host_primary(&d->ssd);
  545. d->mode = QXL_MODE_VGA;
  546. memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
  547. }
  548. static void qxl_exit_vga_mode(PCIQXLDevice *d)
  549. {
  550. if (d->mode != QXL_MODE_VGA) {
  551. return;
  552. }
  553. dprint(d, 1, "%s\n", __FUNCTION__);
  554. qxl_destroy_primary(d);
  555. }
  556. static void qxl_set_irq(PCIQXLDevice *d)
  557. {
  558. uint32_t pending = le32_to_cpu(d->ram->int_pending);
  559. uint32_t mask = le32_to_cpu(d->ram->int_mask);
  560. int level = !!(pending & mask);
  561. qemu_set_irq(d->pci.irq[0], level);
  562. qxl_ring_set_dirty(d);
  563. }
  564. static void qxl_write_config(PCIDevice *d, uint32_t address,
  565. uint32_t val, int len)
  566. {
  567. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, d);
  568. VGACommonState *vga = &qxl->vga;
  569. vga_dirty_log_stop(vga);
  570. pci_default_write_config(d, address, val, len);
  571. if (vga->map_addr && qxl->pci.io_regions[0].addr == -1) {
  572. vga->map_addr = 0;
  573. }
  574. vga_dirty_log_start(vga);
  575. }
  576. static void qxl_check_state(PCIQXLDevice *d)
  577. {
  578. QXLRam *ram = d->ram;
  579. assert(SPICE_RING_IS_EMPTY(&ram->cmd_ring));
  580. assert(SPICE_RING_IS_EMPTY(&ram->cursor_ring));
  581. }
  582. static void qxl_reset_state(PCIQXLDevice *d)
  583. {
  584. QXLRam *ram = d->ram;
  585. QXLRom *rom = d->rom;
  586. assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
  587. assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
  588. d->shadow_rom.update_id = cpu_to_le32(0);
  589. *rom = d->shadow_rom;
  590. qxl_rom_set_dirty(d);
  591. init_qxl_ram(d);
  592. d->num_free_res = 0;
  593. d->last_release = NULL;
  594. memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
  595. }
  596. static void qxl_soft_reset(PCIQXLDevice *d)
  597. {
  598. dprint(d, 1, "%s:\n", __FUNCTION__);
  599. qxl_check_state(d);
  600. if (d->id == 0) {
  601. qxl_enter_vga_mode(d);
  602. } else {
  603. d->mode = QXL_MODE_UNDEFINED;
  604. }
  605. }
  606. static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
  607. {
  608. dprint(d, 1, "%s: start%s\n", __FUNCTION__,
  609. loadvm ? " (loadvm)" : "");
  610. d->ssd.worker->reset_cursor(d->ssd.worker);
  611. d->ssd.worker->reset_image_cache(d->ssd.worker);
  612. qxl_reset_surfaces(d);
  613. qxl_reset_memslots(d);
  614. /* pre loadvm reset must not touch QXLRam. This lives in
  615. * device memory, is migrated together with RAM and thus
  616. * already loaded at this point */
  617. if (!loadvm) {
  618. qxl_reset_state(d);
  619. }
  620. qemu_spice_create_host_memslot(&d->ssd);
  621. qxl_soft_reset(d);
  622. dprint(d, 1, "%s: done\n", __FUNCTION__);
  623. }
  624. static void qxl_reset_handler(DeviceState *dev)
  625. {
  626. PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
  627. qxl_hard_reset(d, 0);
  628. }
  629. static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  630. {
  631. VGACommonState *vga = opaque;
  632. PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
  633. if (qxl->mode != QXL_MODE_VGA) {
  634. dprint(qxl, 1, "%s\n", __FUNCTION__);
  635. qxl_destroy_primary(qxl);
  636. qxl_soft_reset(qxl);
  637. }
  638. vga_ioport_write(opaque, addr, val);
  639. }
  640. static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
  641. {
  642. static const int regions[] = {
  643. QXL_RAM_RANGE_INDEX,
  644. QXL_VRAM_RANGE_INDEX,
  645. };
  646. uint64_t guest_start;
  647. uint64_t guest_end;
  648. int pci_region;
  649. pcibus_t pci_start;
  650. pcibus_t pci_end;
  651. intptr_t virt_start;
  652. QXLDevMemSlot memslot;
  653. int i;
  654. guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
  655. guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
  656. dprint(d, 1, "%s: slot %d: guest phys 0x%" PRIx64 " - 0x%" PRIx64 "\n",
  657. __FUNCTION__, slot_id,
  658. guest_start, guest_end);
  659. PANIC_ON(slot_id >= NUM_MEMSLOTS);
  660. PANIC_ON(guest_start > guest_end);
  661. for (i = 0; i < ARRAY_SIZE(regions); i++) {
  662. pci_region = regions[i];
  663. pci_start = d->pci.io_regions[pci_region].addr;
  664. pci_end = pci_start + d->pci.io_regions[pci_region].size;
  665. /* mapped? */
  666. if (pci_start == -1) {
  667. continue;
  668. }
  669. /* start address in range ? */
  670. if (guest_start < pci_start || guest_start > pci_end) {
  671. continue;
  672. }
  673. /* end address in range ? */
  674. if (guest_end > pci_end) {
  675. continue;
  676. }
  677. /* passed */
  678. break;
  679. }
  680. PANIC_ON(i == ARRAY_SIZE(regions)); /* finished loop without match */
  681. switch (pci_region) {
  682. case QXL_RAM_RANGE_INDEX:
  683. virt_start = (intptr_t)qemu_get_ram_ptr(d->vga.vram_offset);
  684. break;
  685. case QXL_VRAM_RANGE_INDEX:
  686. virt_start = (intptr_t)qemu_get_ram_ptr(d->vram_offset);
  687. break;
  688. default:
  689. /* should not happen */
  690. abort();
  691. }
  692. memslot.slot_id = slot_id;
  693. memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
  694. memslot.virt_start = virt_start + (guest_start - pci_start);
  695. memslot.virt_end = virt_start + (guest_end - pci_start);
  696. memslot.addr_delta = memslot.virt_start - delta;
  697. memslot.generation = d->rom->slot_generation = 0;
  698. qxl_rom_set_dirty(d);
  699. dprint(d, 1, "%s: slot %d: host virt 0x%" PRIx64 " - 0x%" PRIx64 "\n",
  700. __FUNCTION__, memslot.slot_id,
  701. memslot.virt_start, memslot.virt_end);
  702. d->ssd.worker->add_memslot(d->ssd.worker, &memslot);
  703. d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
  704. d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
  705. d->guest_slots[slot_id].delta = delta;
  706. d->guest_slots[slot_id].active = 1;
  707. }
  708. static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
  709. {
  710. dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
  711. d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id);
  712. d->guest_slots[slot_id].active = 0;
  713. }
  714. static void qxl_reset_memslots(PCIQXLDevice *d)
  715. {
  716. dprint(d, 1, "%s:\n", __FUNCTION__);
  717. d->ssd.worker->reset_memslots(d->ssd.worker);
  718. memset(&d->guest_slots, 0, sizeof(d->guest_slots));
  719. }
  720. static void qxl_reset_surfaces(PCIQXLDevice *d)
  721. {
  722. dprint(d, 1, "%s:\n", __FUNCTION__);
  723. d->mode = QXL_MODE_UNDEFINED;
  724. d->ssd.worker->destroy_surfaces(d->ssd.worker);
  725. memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
  726. }
  727. /* called from spice server thread context only */
  728. void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
  729. {
  730. uint64_t phys = le64_to_cpu(pqxl);
  731. uint32_t slot = (phys >> (64 - 8)) & 0xff;
  732. uint64_t offset = phys & 0xffffffffffff;
  733. switch (group_id) {
  734. case MEMSLOT_GROUP_HOST:
  735. return (void*)offset;
  736. case MEMSLOT_GROUP_GUEST:
  737. PANIC_ON(slot > NUM_MEMSLOTS);
  738. PANIC_ON(!qxl->guest_slots[slot].active);
  739. PANIC_ON(offset < qxl->guest_slots[slot].delta);
  740. offset -= qxl->guest_slots[slot].delta;
  741. PANIC_ON(offset > qxl->guest_slots[slot].size)
  742. return qxl->guest_slots[slot].ptr + offset;
  743. default:
  744. PANIC_ON(1);
  745. }
  746. }
  747. static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
  748. {
  749. QXLDevSurfaceCreate surface;
  750. QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
  751. assert(qxl->mode != QXL_MODE_NATIVE);
  752. qxl_exit_vga_mode(qxl);
  753. dprint(qxl, 1, "%s: %dx%d\n", __FUNCTION__,
  754. le32_to_cpu(sc->width), le32_to_cpu(sc->height));
  755. surface.format = le32_to_cpu(sc->format);
  756. surface.height = le32_to_cpu(sc->height);
  757. surface.mem = le64_to_cpu(sc->mem);
  758. surface.position = le32_to_cpu(sc->position);
  759. surface.stride = le32_to_cpu(sc->stride);
  760. surface.width = le32_to_cpu(sc->width);
  761. surface.type = le32_to_cpu(sc->type);
  762. surface.flags = le32_to_cpu(sc->flags);
  763. surface.mouse_mode = true;
  764. surface.group_id = MEMSLOT_GROUP_GUEST;
  765. if (loadvm) {
  766. surface.flags |= QXL_SURF_FLAG_KEEP_DATA;
  767. }
  768. qxl->mode = QXL_MODE_NATIVE;
  769. qxl->cmdflags = 0;
  770. qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface);
  771. /* for local rendering */
  772. qxl_render_resize(qxl);
  773. }
  774. static void qxl_destroy_primary(PCIQXLDevice *d)
  775. {
  776. if (d->mode == QXL_MODE_UNDEFINED) {
  777. return;
  778. }
  779. dprint(d, 1, "%s\n", __FUNCTION__);
  780. d->mode = QXL_MODE_UNDEFINED;
  781. d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
  782. }
  783. static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
  784. {
  785. pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
  786. pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start;
  787. QXLMode *mode = d->modes->modes + modenr;
  788. uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
  789. QXLMemSlot slot = {
  790. .mem_start = start,
  791. .mem_end = end
  792. };
  793. QXLSurfaceCreate surface = {
  794. .width = mode->x_res,
  795. .height = mode->y_res,
  796. .stride = -mode->x_res * 4,
  797. .format = SPICE_SURFACE_FMT_32_xRGB,
  798. .flags = loadvm ? QXL_SURF_FLAG_KEEP_DATA : 0,
  799. .mouse_mode = true,
  800. .mem = devmem + d->shadow_rom.draw_area_offset,
  801. };
  802. dprint(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%lx ]\n", __FUNCTION__,
  803. modenr, mode->x_res, mode->y_res, mode->bits, devmem);
  804. if (!loadvm) {
  805. qxl_hard_reset(d, 0);
  806. }
  807. d->guest_slots[0].slot = slot;
  808. qxl_add_memslot(d, 0, devmem);
  809. d->guest_primary.surface = surface;
  810. qxl_create_guest_primary(d, 0);
  811. d->mode = QXL_MODE_COMPAT;
  812. d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
  813. #ifdef QXL_COMMAND_FLAG_COMPAT_16BPP /* new in spice 0.6.1 */
  814. if (mode->bits == 16) {
  815. d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP;
  816. }
  817. #endif
  818. d->shadow_rom.mode = cpu_to_le32(modenr);
  819. d->rom->mode = cpu_to_le32(modenr);
  820. qxl_rom_set_dirty(d);
  821. }
  822. static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
  823. {
  824. PCIQXLDevice *d = opaque;
  825. uint32_t io_port = addr - d->io_base;
  826. switch (io_port) {
  827. case QXL_IO_RESET:
  828. case QXL_IO_SET_MODE:
  829. case QXL_IO_MEMSLOT_ADD:
  830. case QXL_IO_MEMSLOT_DEL:
  831. case QXL_IO_CREATE_PRIMARY:
  832. case QXL_IO_UPDATE_IRQ:
  833. case QXL_IO_LOG:
  834. break;
  835. default:
  836. if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
  837. break;
  838. dprint(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port);
  839. return;
  840. }
  841. switch (io_port) {
  842. case QXL_IO_UPDATE_AREA:
  843. {
  844. QXLRect update = d->ram->update_area;
  845. d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
  846. &update, NULL, 0, 0);
  847. break;
  848. }
  849. case QXL_IO_NOTIFY_CMD:
  850. d->ssd.worker->wakeup(d->ssd.worker);
  851. break;
  852. case QXL_IO_NOTIFY_CURSOR:
  853. d->ssd.worker->wakeup(d->ssd.worker);
  854. break;
  855. case QXL_IO_UPDATE_IRQ:
  856. qxl_set_irq(d);
  857. break;
  858. case QXL_IO_NOTIFY_OOM:
  859. if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
  860. break;
  861. }
  862. pthread_yield();
  863. if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
  864. break;
  865. }
  866. d->oom_running = 1;
  867. d->ssd.worker->oom(d->ssd.worker);
  868. d->oom_running = 0;
  869. break;
  870. case QXL_IO_SET_MODE:
  871. dprint(d, 1, "QXL_SET_MODE %d\n", val);
  872. qxl_set_mode(d, val, 0);
  873. break;
  874. case QXL_IO_LOG:
  875. if (d->guestdebug) {
  876. fprintf(stderr, "qxl/guest-%d: %ld: %s", d->id,
  877. qemu_get_clock_ns(vm_clock), d->ram->log_buf);
  878. }
  879. break;
  880. case QXL_IO_RESET:
  881. dprint(d, 1, "QXL_IO_RESET\n");
  882. qxl_hard_reset(d, 0);
  883. break;
  884. case QXL_IO_MEMSLOT_ADD:
  885. PANIC_ON(val >= NUM_MEMSLOTS);
  886. PANIC_ON(d->guest_slots[val].active);
  887. d->guest_slots[val].slot = d->ram->mem_slot;
  888. qxl_add_memslot(d, val, 0);
  889. break;
  890. case QXL_IO_MEMSLOT_DEL:
  891. qxl_del_memslot(d, val);
  892. break;
  893. case QXL_IO_CREATE_PRIMARY:
  894. PANIC_ON(val != 0);
  895. dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n");
  896. d->guest_primary.surface = d->ram->create_surface;
  897. qxl_create_guest_primary(d, 0);
  898. break;
  899. case QXL_IO_DESTROY_PRIMARY:
  900. PANIC_ON(val != 0);
  901. dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
  902. qxl_destroy_primary(d);
  903. break;
  904. case QXL_IO_DESTROY_SURFACE_WAIT:
  905. d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
  906. break;
  907. case QXL_IO_DESTROY_ALL_SURFACES:
  908. d->ssd.worker->destroy_surfaces(d->ssd.worker);
  909. break;
  910. default:
  911. fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
  912. abort();
  913. }
  914. }
  915. static uint32_t ioport_read(void *opaque, uint32_t addr)
  916. {
  917. PCIQXLDevice *d = opaque;
  918. dprint(d, 1, "%s: unexpected\n", __FUNCTION__);
  919. return 0xff;
  920. }
  921. static void qxl_map(PCIDevice *pci, int region_num,
  922. pcibus_t addr, pcibus_t size, int type)
  923. {
  924. static const char *names[] = {
  925. [ QXL_IO_RANGE_INDEX ] = "ioports",
  926. [ QXL_RAM_RANGE_INDEX ] = "devram",
  927. [ QXL_ROM_RANGE_INDEX ] = "rom",
  928. [ QXL_VRAM_RANGE_INDEX ] = "vram",
  929. };
  930. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, pci);
  931. dprint(qxl, 1, "%s: bar %d [%s] addr 0x%lx size 0x%lx\n", __FUNCTION__,
  932. region_num, names[region_num], addr, size);
  933. switch (region_num) {
  934. case QXL_IO_RANGE_INDEX:
  935. register_ioport_write(addr, size, 1, ioport_write, pci);
  936. register_ioport_read(addr, size, 1, ioport_read, pci);
  937. qxl->io_base = addr;
  938. break;
  939. case QXL_RAM_RANGE_INDEX:
  940. cpu_register_physical_memory(addr, size, qxl->vga.vram_offset | IO_MEM_RAM);
  941. qxl->vga.map_addr = addr;
  942. qxl->vga.map_end = addr + size;
  943. if (qxl->id == 0) {
  944. vga_dirty_log_start(&qxl->vga);
  945. }
  946. break;
  947. case QXL_ROM_RANGE_INDEX:
  948. cpu_register_physical_memory(addr, size, qxl->rom_offset | IO_MEM_ROM);
  949. break;
  950. case QXL_VRAM_RANGE_INDEX:
  951. cpu_register_physical_memory(addr, size, qxl->vram_offset | IO_MEM_RAM);
  952. break;
  953. }
  954. }
  955. static void pipe_read(void *opaque)
  956. {
  957. PCIQXLDevice *d = opaque;
  958. char dummy;
  959. int len;
  960. do {
  961. len = read(d->pipe[0], &dummy, sizeof(dummy));
  962. } while (len == sizeof(dummy));
  963. qxl_set_irq(d);
  964. }
  965. /* called from spice server thread context only */
  966. static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
  967. {
  968. uint32_t old_pending;
  969. uint32_t le_events = cpu_to_le32(events);
  970. assert(d->ssd.running);
  971. old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
  972. if ((old_pending & le_events) == le_events) {
  973. return;
  974. }
  975. if (pthread_self() == d->main) {
  976. qxl_set_irq(d);
  977. } else {
  978. if (write(d->pipe[1], d, 1) != 1) {
  979. dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
  980. }
  981. }
  982. }
  983. static void init_pipe_signaling(PCIQXLDevice *d)
  984. {
  985. if (pipe(d->pipe) < 0) {
  986. dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
  987. return;
  988. }
  989. #ifdef CONFIG_IOTHREAD
  990. fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
  991. #else
  992. fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
  993. #endif
  994. fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
  995. fcntl(d->pipe[0], F_SETOWN, getpid());
  996. d->main = pthread_self();
  997. qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
  998. }
  999. /* graphics console */
  1000. static void qxl_hw_update(void *opaque)
  1001. {
  1002. PCIQXLDevice *qxl = opaque;
  1003. VGACommonState *vga = &qxl->vga;
  1004. switch (qxl->mode) {
  1005. case QXL_MODE_VGA:
  1006. vga->update(vga);
  1007. break;
  1008. case QXL_MODE_COMPAT:
  1009. case QXL_MODE_NATIVE:
  1010. qxl_render_update(qxl);
  1011. break;
  1012. default:
  1013. break;
  1014. }
  1015. }
  1016. static void qxl_hw_invalidate(void *opaque)
  1017. {
  1018. PCIQXLDevice *qxl = opaque;
  1019. VGACommonState *vga = &qxl->vga;
  1020. vga->invalidate(vga);
  1021. }
  1022. static void qxl_hw_screen_dump(void *opaque, const char *filename)
  1023. {
  1024. PCIQXLDevice *qxl = opaque;
  1025. VGACommonState *vga = &qxl->vga;
  1026. switch (qxl->mode) {
  1027. case QXL_MODE_COMPAT:
  1028. case QXL_MODE_NATIVE:
  1029. qxl_render_update(qxl);
  1030. ppm_save(filename, qxl->ssd.ds->surface);
  1031. break;
  1032. case QXL_MODE_VGA:
  1033. vga->screen_dump(vga, filename);
  1034. break;
  1035. default:
  1036. break;
  1037. }
  1038. }
  1039. static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
  1040. {
  1041. PCIQXLDevice *qxl = opaque;
  1042. VGACommonState *vga = &qxl->vga;
  1043. if (qxl->mode == QXL_MODE_VGA) {
  1044. vga->text_update(vga, chardata);
  1045. return;
  1046. }
  1047. }
  1048. static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
  1049. {
  1050. PCIQXLDevice *qxl = opaque;
  1051. qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
  1052. if (!running && qxl->mode == QXL_MODE_NATIVE) {
  1053. /* dirty all vram (which holds surfaces) and devram (primary surface)
  1054. * to make sure they are saved */
  1055. /* FIXME #1: should go out during "live" stage */
  1056. /* FIXME #2: we only need to save the areas which are actually used */
  1057. ram_addr_t vram_addr = qxl->vram_offset;
  1058. ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset;
  1059. qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size);
  1060. qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size);
  1061. }
  1062. }
  1063. /* display change listener */
  1064. static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
  1065. {
  1066. if (qxl0->mode == QXL_MODE_VGA) {
  1067. qemu_spice_display_update(&qxl0->ssd, x, y, w, h);
  1068. }
  1069. }
  1070. static void display_resize(struct DisplayState *ds)
  1071. {
  1072. if (qxl0->mode == QXL_MODE_VGA) {
  1073. qemu_spice_display_resize(&qxl0->ssd);
  1074. }
  1075. }
  1076. static void display_refresh(struct DisplayState *ds)
  1077. {
  1078. if (qxl0->mode == QXL_MODE_VGA) {
  1079. qemu_spice_display_refresh(&qxl0->ssd);
  1080. }
  1081. }
  1082. static DisplayChangeListener display_listener = {
  1083. .dpy_update = display_update,
  1084. .dpy_resize = display_resize,
  1085. .dpy_refresh = display_refresh,
  1086. };
  1087. static int qxl_init_common(PCIQXLDevice *qxl)
  1088. {
  1089. uint8_t* config = qxl->pci.config;
  1090. uint32_t pci_device_rev;
  1091. uint32_t io_size;
  1092. qxl->mode = QXL_MODE_UNDEFINED;
  1093. qxl->generation = 1;
  1094. qxl->num_memslots = NUM_MEMSLOTS;
  1095. qxl->num_surfaces = NUM_SURFACES;
  1096. switch (qxl->revision) {
  1097. case 1: /* spice 0.4 -- qxl-1 */
  1098. pci_device_rev = QXL_REVISION_STABLE_V04;
  1099. break;
  1100. case 2: /* spice 0.6 -- qxl-2 */
  1101. default:
  1102. pci_device_rev = QXL_REVISION_STABLE_V06;
  1103. break;
  1104. }
  1105. pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
  1106. pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
  1107. qxl->rom_size = qxl_rom_size();
  1108. qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
  1109. init_qxl_rom(qxl);
  1110. init_qxl_ram(qxl);
  1111. if (qxl->vram_size < 16 * 1024 * 1024) {
  1112. qxl->vram_size = 16 * 1024 * 1024;
  1113. }
  1114. if (qxl->revision == 1) {
  1115. qxl->vram_size = 4096;
  1116. }
  1117. qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
  1118. qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
  1119. io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
  1120. if (qxl->revision == 1) {
  1121. io_size = 8;
  1122. }
  1123. pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
  1124. io_size, PCI_BASE_ADDRESS_SPACE_IO, qxl_map);
  1125. pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
  1126. qxl->rom_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
  1127. qxl_map);
  1128. pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
  1129. qxl->vga.vram_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
  1130. qxl_map);
  1131. pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, qxl->vram_size,
  1132. PCI_BASE_ADDRESS_SPACE_MEMORY, qxl_map);
  1133. qxl->ssd.qxl.base.sif = &qxl_interface.base;
  1134. qxl->ssd.qxl.id = qxl->id;
  1135. qemu_spice_add_interface(&qxl->ssd.qxl.base);
  1136. qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
  1137. init_pipe_signaling(qxl);
  1138. qxl_reset_state(qxl);
  1139. return 0;
  1140. }
  1141. static int qxl_init_primary(PCIDevice *dev)
  1142. {
  1143. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
  1144. VGACommonState *vga = &qxl->vga;
  1145. ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
  1146. qxl->id = 0;
  1147. if (ram_size < 32 * 1024 * 1024) {
  1148. ram_size = 32 * 1024 * 1024;
  1149. }
  1150. vga_common_init(vga, ram_size);
  1151. vga_init(vga);
  1152. register_ioport_write(0x3c0, 16, 1, qxl_vga_ioport_write, vga);
  1153. register_ioport_write(0x3b4, 2, 1, qxl_vga_ioport_write, vga);
  1154. register_ioport_write(0x3d4, 2, 1, qxl_vga_ioport_write, vga);
  1155. register_ioport_write(0x3ba, 1, 1, qxl_vga_ioport_write, vga);
  1156. register_ioport_write(0x3da, 1, 1, qxl_vga_ioport_write, vga);
  1157. vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
  1158. qxl_hw_screen_dump, qxl_hw_text_update, qxl);
  1159. qxl->ssd.ds = vga->ds;
  1160. qemu_mutex_init(&qxl->ssd.lock);
  1161. qxl->ssd.mouse_x = -1;
  1162. qxl->ssd.mouse_y = -1;
  1163. qxl->ssd.bufsize = (16 * 1024 * 1024);
  1164. qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
  1165. qxl0 = qxl;
  1166. register_displaychangelistener(vga->ds, &display_listener);
  1167. return qxl_init_common(qxl);
  1168. }
  1169. static int qxl_init_secondary(PCIDevice *dev)
  1170. {
  1171. static int device_id = 1;
  1172. PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
  1173. ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
  1174. qxl->id = device_id++;
  1175. if (ram_size < 16 * 1024 * 1024) {
  1176. ram_size = 16 * 1024 * 1024;
  1177. }
  1178. qxl->vga.vram_size = ram_size;
  1179. qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
  1180. qxl->vga.vram_size);
  1181. qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
  1182. return qxl_init_common(qxl);
  1183. }
  1184. static void qxl_pre_save(void *opaque)
  1185. {
  1186. PCIQXLDevice* d = opaque;
  1187. uint8_t *ram_start = d->vga.vram_ptr;
  1188. dprint(d, 1, "%s:\n", __FUNCTION__);
  1189. if (d->last_release == NULL) {
  1190. d->last_release_offset = 0;
  1191. } else {
  1192. d->last_release_offset = (uint8_t *)d->last_release - ram_start;
  1193. }
  1194. assert(d->last_release_offset < d->vga.vram_size);
  1195. }
  1196. static int qxl_pre_load(void *opaque)
  1197. {
  1198. PCIQXLDevice* d = opaque;
  1199. dprint(d, 1, "%s: start\n", __FUNCTION__);
  1200. qxl_hard_reset(d, 1);
  1201. qxl_exit_vga_mode(d);
  1202. dprint(d, 1, "%s: done\n", __FUNCTION__);
  1203. return 0;
  1204. }
  1205. static int qxl_post_load(void *opaque, int version)
  1206. {
  1207. PCIQXLDevice* d = opaque;
  1208. uint8_t *ram_start = d->vga.vram_ptr;
  1209. QXLCommandExt *cmds;
  1210. int in, out, i, newmode;
  1211. dprint(d, 1, "%s: start\n", __FUNCTION__);
  1212. assert(d->last_release_offset < d->vga.vram_size);
  1213. if (d->last_release_offset == 0) {
  1214. d->last_release = NULL;
  1215. } else {
  1216. d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
  1217. }
  1218. d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
  1219. dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
  1220. qxl_mode_to_string(d->mode));
  1221. newmode = d->mode;
  1222. d->mode = QXL_MODE_UNDEFINED;
  1223. switch (newmode) {
  1224. case QXL_MODE_UNDEFINED:
  1225. break;
  1226. case QXL_MODE_VGA:
  1227. qxl_enter_vga_mode(d);
  1228. break;
  1229. case QXL_MODE_NATIVE:
  1230. for (i = 0; i < NUM_MEMSLOTS; i++) {
  1231. if (!d->guest_slots[i].active) {
  1232. continue;
  1233. }
  1234. qxl_add_memslot(d, i, 0);
  1235. }
  1236. qxl_create_guest_primary(d, 1);
  1237. /* replay surface-create and cursor-set commands */
  1238. cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1));
  1239. for (in = 0, out = 0; in < NUM_SURFACES; in++) {
  1240. if (d->guest_surfaces.cmds[in] == 0) {
  1241. continue;
  1242. }
  1243. cmds[out].cmd.data = d->guest_surfaces.cmds[in];
  1244. cmds[out].cmd.type = QXL_CMD_SURFACE;
  1245. cmds[out].group_id = MEMSLOT_GROUP_GUEST;
  1246. out++;
  1247. }
  1248. cmds[out].cmd.data = d->guest_cursor;
  1249. cmds[out].cmd.type = QXL_CMD_CURSOR;
  1250. cmds[out].group_id = MEMSLOT_GROUP_GUEST;
  1251. out++;
  1252. d->ssd.worker->loadvm_commands(d->ssd.worker, cmds, out);
  1253. qemu_free(cmds);
  1254. break;
  1255. case QXL_MODE_COMPAT:
  1256. qxl_set_mode(d, d->shadow_rom.mode, 1);
  1257. break;
  1258. }
  1259. dprint(d, 1, "%s: done\n", __FUNCTION__);
  1260. return 0;
  1261. }
  1262. #define QXL_SAVE_VERSION 21
  1263. static VMStateDescription qxl_memslot = {
  1264. .name = "qxl-memslot",
  1265. .version_id = QXL_SAVE_VERSION,
  1266. .minimum_version_id = QXL_SAVE_VERSION,
  1267. .fields = (VMStateField[]) {
  1268. VMSTATE_UINT64(slot.mem_start, struct guest_slots),
  1269. VMSTATE_UINT64(slot.mem_end, struct guest_slots),
  1270. VMSTATE_UINT32(active, struct guest_slots),
  1271. VMSTATE_END_OF_LIST()
  1272. }
  1273. };
  1274. static VMStateDescription qxl_surface = {
  1275. .name = "qxl-surface",
  1276. .version_id = QXL_SAVE_VERSION,
  1277. .minimum_version_id = QXL_SAVE_VERSION,
  1278. .fields = (VMStateField[]) {
  1279. VMSTATE_UINT32(width, QXLSurfaceCreate),
  1280. VMSTATE_UINT32(height, QXLSurfaceCreate),
  1281. VMSTATE_INT32(stride, QXLSurfaceCreate),
  1282. VMSTATE_UINT32(format, QXLSurfaceCreate),
  1283. VMSTATE_UINT32(position, QXLSurfaceCreate),
  1284. VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate),
  1285. VMSTATE_UINT32(flags, QXLSurfaceCreate),
  1286. VMSTATE_UINT32(type, QXLSurfaceCreate),
  1287. VMSTATE_UINT64(mem, QXLSurfaceCreate),
  1288. VMSTATE_END_OF_LIST()
  1289. }
  1290. };
  1291. static VMStateDescription qxl_vmstate = {
  1292. .name = "qxl",
  1293. .version_id = QXL_SAVE_VERSION,
  1294. .minimum_version_id = QXL_SAVE_VERSION,
  1295. .pre_save = qxl_pre_save,
  1296. .pre_load = qxl_pre_load,
  1297. .post_load = qxl_post_load,
  1298. .fields = (VMStateField []) {
  1299. VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
  1300. VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
  1301. VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
  1302. VMSTATE_UINT32(num_free_res, PCIQXLDevice),
  1303. VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
  1304. VMSTATE_UINT32(mode, PCIQXLDevice),
  1305. VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
  1306. VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
  1307. VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
  1308. qxl_memslot, struct guest_slots),
  1309. VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
  1310. qxl_surface, QXLSurfaceCreate),
  1311. VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
  1312. VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
  1313. vmstate_info_uint64, uint64_t),
  1314. VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
  1315. VMSTATE_END_OF_LIST()
  1316. },
  1317. };
  1318. static PCIDeviceInfo qxl_info_primary = {
  1319. .qdev.name = "qxl-vga",
  1320. .qdev.desc = "Spice QXL GPU (primary, vga compatible)",
  1321. .qdev.size = sizeof(PCIQXLDevice),
  1322. .qdev.reset = qxl_reset_handler,
  1323. .qdev.vmsd = &qxl_vmstate,
  1324. .no_hotplug = 1,
  1325. .init = qxl_init_primary,
  1326. .config_write = qxl_write_config,
  1327. .romfile = "vgabios-qxl.bin",
  1328. .vendor_id = REDHAT_PCI_VENDOR_ID,
  1329. .device_id = QXL_DEVICE_ID_STABLE,
  1330. .class_id = PCI_CLASS_DISPLAY_VGA,
  1331. .qdev.props = (Property[]) {
  1332. DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
  1333. DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
  1334. DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
  1335. DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
  1336. DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
  1337. DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
  1338. DEFINE_PROP_END_OF_LIST(),
  1339. }
  1340. };
  1341. static PCIDeviceInfo qxl_info_secondary = {
  1342. .qdev.name = "qxl",
  1343. .qdev.desc = "Spice QXL GPU (secondary)",
  1344. .qdev.size = sizeof(PCIQXLDevice),
  1345. .qdev.reset = qxl_reset_handler,
  1346. .qdev.vmsd = &qxl_vmstate,
  1347. .init = qxl_init_secondary,
  1348. .vendor_id = REDHAT_PCI_VENDOR_ID,
  1349. .device_id = QXL_DEVICE_ID_STABLE,
  1350. .class_id = PCI_CLASS_DISPLAY_OTHER,
  1351. .qdev.props = (Property[]) {
  1352. DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
  1353. DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
  1354. DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
  1355. DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
  1356. DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
  1357. DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
  1358. DEFINE_PROP_END_OF_LIST(),
  1359. }
  1360. };
  1361. static void qxl_register(void)
  1362. {
  1363. pci_qdev_register(&qxl_info_primary);
  1364. pci_qdev_register(&qxl_info_secondary);
  1365. }
  1366. device_init(qxl_register);