147b43a1fSPaolo Bonzini #ifndef HW_QXL_H 2175de524SMarkus Armbruster #define HW_QXL_H 347b43a1fSPaolo Bonzini 4edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h" 547b43a1fSPaolo Bonzini #include "vga_int.h" 647b43a1fSPaolo Bonzini #include "qemu/thread.h" 747b43a1fSPaolo Bonzini 847b43a1fSPaolo Bonzini #include "ui/qemu-spice.h" 947b43a1fSPaolo Bonzini #include "ui/spice-display.h" 10db1015e9SEduardo Habkost #include "qom/object.h" 1147b43a1fSPaolo Bonzini 1247b43a1fSPaolo Bonzini enum qxl_mode { 1347b43a1fSPaolo Bonzini QXL_MODE_UNDEFINED, 1447b43a1fSPaolo Bonzini QXL_MODE_VGA, 1547b43a1fSPaolo Bonzini QXL_MODE_COMPAT, /* spice 0.4.x */ 1647b43a1fSPaolo Bonzini QXL_MODE_NATIVE, 1747b43a1fSPaolo Bonzini }; 1847b43a1fSPaolo Bonzini 1947b43a1fSPaolo Bonzini #ifndef QXL_VRAM64_RANGE_INDEX 2047b43a1fSPaolo Bonzini #define QXL_VRAM64_RANGE_INDEX 4 2147b43a1fSPaolo Bonzini #endif 2247b43a1fSPaolo Bonzini 2347b43a1fSPaolo Bonzini #define QXL_UNDEFINED_IO UINT32_MAX 2447b43a1fSPaolo Bonzini 2547b43a1fSPaolo Bonzini #define QXL_NUM_DIRTY_RECTS 64 2647b43a1fSPaolo Bonzini 279efc2d8dSGerd Hoffmann #define QXL_PAGE_BITS 12 289efc2d8dSGerd Hoffmann #define QXL_PAGE_SIZE (1 << QXL_PAGE_BITS); 299efc2d8dSGerd Hoffmann 30db1015e9SEduardo Habkost struct PCIQXLDevice { 3147b43a1fSPaolo Bonzini PCIDevice pci; 32848696bfSKirill Batuzov PortioList vga_port_list; 3347b43a1fSPaolo Bonzini SimpleSpiceDisplay ssd; 3447b43a1fSPaolo Bonzini int id; 3560e94e43SGerd Hoffmann bool have_vga; 3647b43a1fSPaolo Bonzini uint32_t debug; 3747b43a1fSPaolo Bonzini uint32_t guestdebug; 3847b43a1fSPaolo Bonzini uint32_t cmdlog; 3947b43a1fSPaolo Bonzini 4047b43a1fSPaolo Bonzini uint32_t guest_bug; 4147b43a1fSPaolo Bonzini 4247b43a1fSPaolo Bonzini enum qxl_mode mode; 4347b43a1fSPaolo Bonzini uint32_t cmdflags; 4447b43a1fSPaolo Bonzini uint32_t revision; 4547b43a1fSPaolo Bonzini 4647b43a1fSPaolo Bonzini int32_t num_memslots; 4747b43a1fSPaolo Bonzini 4847b43a1fSPaolo Bonzini uint32_t current_async; 4947b43a1fSPaolo Bonzini QemuMutex async_lock; 5047b43a1fSPaolo Bonzini 5147b43a1fSPaolo Bonzini struct guest_slots { 5247b43a1fSPaolo Bonzini QXLMemSlot slot; 533cb5158fSGerd Hoffmann MemoryRegion *mr; 543cb5158fSGerd Hoffmann uint64_t offset; 5547b43a1fSPaolo Bonzini uint64_t size; 5647b43a1fSPaolo Bonzini uint64_t delta; 5747b43a1fSPaolo Bonzini uint32_t active; 5847b43a1fSPaolo Bonzini } guest_slots[NUM_MEMSLOTS]; 5947b43a1fSPaolo Bonzini 6047b43a1fSPaolo Bonzini struct guest_primary { 6147b43a1fSPaolo Bonzini QXLSurfaceCreate surface; 6247b43a1fSPaolo Bonzini uint32_t commands; 6347b43a1fSPaolo Bonzini uint32_t resized; 6447b43a1fSPaolo Bonzini int32_t qxl_stride; 6547b43a1fSPaolo Bonzini uint32_t abs_stride; 6647b43a1fSPaolo Bonzini uint32_t bits_pp; 6747b43a1fSPaolo Bonzini uint32_t bytes_pp; 6847b43a1fSPaolo Bonzini uint8_t *data; 6947b43a1fSPaolo Bonzini } guest_primary; 7047b43a1fSPaolo Bonzini 7147b43a1fSPaolo Bonzini struct surfaces { 7247b43a1fSPaolo Bonzini QXLPHYSICAL *cmds; 7347b43a1fSPaolo Bonzini uint32_t count; 7447b43a1fSPaolo Bonzini uint32_t max; 7547b43a1fSPaolo Bonzini } guest_surfaces; 7647b43a1fSPaolo Bonzini QXLPHYSICAL guest_cursor; 7747b43a1fSPaolo Bonzini 7847b43a1fSPaolo Bonzini QXLPHYSICAL guest_monitors_config; 79979f7ef8SGerd Hoffmann uint32_t guest_head0_width; 80979f7ef8SGerd Hoffmann uint32_t guest_head0_height; 8147b43a1fSPaolo Bonzini 8247b43a1fSPaolo Bonzini QemuMutex track_lock; 8347b43a1fSPaolo Bonzini 8447b43a1fSPaolo Bonzini /* thread signaling */ 854a46c99cSGerd Hoffmann QEMUBH *update_irq; 8647b43a1fSPaolo Bonzini 8747b43a1fSPaolo Bonzini /* ram pci bar */ 8847b43a1fSPaolo Bonzini QXLRam *ram; 8947b43a1fSPaolo Bonzini VGACommonState vga; 9047b43a1fSPaolo Bonzini uint32_t num_free_res; 9147b43a1fSPaolo Bonzini QXLReleaseInfo *last_release; 9247b43a1fSPaolo Bonzini uint32_t last_release_offset; 9347b43a1fSPaolo Bonzini uint32_t oom_running; 9447b43a1fSPaolo Bonzini uint32_t vgamem_size; 9547b43a1fSPaolo Bonzini 9647b43a1fSPaolo Bonzini /* rom pci bar */ 9747b43a1fSPaolo Bonzini QXLRom shadow_rom; 9847b43a1fSPaolo Bonzini QXLRom *rom; 9947b43a1fSPaolo Bonzini QXLModes *modes; 10047b43a1fSPaolo Bonzini uint32_t rom_size; 10147b43a1fSPaolo Bonzini MemoryRegion rom_bar; 102567161fdSFrediano Ziglio uint16_t max_outputs; 10347b43a1fSPaolo Bonzini 10447b43a1fSPaolo Bonzini /* vram pci bar */ 105de1b9b85SGerd Hoffmann uint64_t vram_size; 10647b43a1fSPaolo Bonzini MemoryRegion vram_bar; 107de1b9b85SGerd Hoffmann uint64_t vram32_size; 10847b43a1fSPaolo Bonzini MemoryRegion vram32_bar; 10947b43a1fSPaolo Bonzini 11047b43a1fSPaolo Bonzini /* io bar */ 11147b43a1fSPaolo Bonzini MemoryRegion io_bar; 11247b43a1fSPaolo Bonzini 11347b43a1fSPaolo Bonzini /* user-friendly properties (in megabytes) */ 11447b43a1fSPaolo Bonzini uint32_t ram_size_mb; 11547b43a1fSPaolo Bonzini uint32_t vram_size_mb; 11647b43a1fSPaolo Bonzini uint32_t vram32_size_mb; 11747b43a1fSPaolo Bonzini uint32_t vgamem_size_mb; 1186f663d7bSGerd Hoffmann uint32_t xres; 1196f663d7bSGerd Hoffmann uint32_t yres; 12047b43a1fSPaolo Bonzini 12147b43a1fSPaolo Bonzini /* qxl_render_update state */ 12247b43a1fSPaolo Bonzini int render_update_cookie_num; 12347b43a1fSPaolo Bonzini int num_dirty_rects; 12447b43a1fSPaolo Bonzini QXLRect dirty[QXL_NUM_DIRTY_RECTS]; 12547b43a1fSPaolo Bonzini QEMUBH *update_area_bh; 126db1015e9SEduardo Habkost }; 12747b43a1fSPaolo Bonzini 128c69f6c7dSGonglei #define TYPE_PCI_QXL "pci-qxl" 1298063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(PCIQXLDevice, PCI_QXL) 130c69f6c7dSGonglei 13147b43a1fSPaolo Bonzini #define PANIC_ON(x) if ((x)) { \ 132a89f364aSAlistair Francis printf("%s: PANIC %s failed\n", __func__, #x); \ 13347b43a1fSPaolo Bonzini abort(); \ 13447b43a1fSPaolo Bonzini } 13547b43a1fSPaolo Bonzini 13647b43a1fSPaolo Bonzini #define dprint(_qxl, _level, _fmt, ...) \ 13747b43a1fSPaolo Bonzini do { \ 13847b43a1fSPaolo Bonzini if (_qxl->debug >= _level) { \ 13947b43a1fSPaolo Bonzini fprintf(stderr, "qxl-%d: ", _qxl->id); \ 14047b43a1fSPaolo Bonzini fprintf(stderr, _fmt, ## __VA_ARGS__); \ 14147b43a1fSPaolo Bonzini } \ 14247b43a1fSPaolo Bonzini } while (0) 14347b43a1fSPaolo Bonzini 144ed71c09fSGerd Hoffmann #define QXL_DEFAULT_REVISION (QXL_REVISION_STABLE_V12 + 1) 14547b43a1fSPaolo Bonzini 14647b43a1fSPaolo Bonzini /* qxl.c */ 147b1901de8SPhilippe Mathieu-Daudé /** 148b1901de8SPhilippe Mathieu-Daudé * qxl_phys2virt: Get a pointer within a PCI VRAM memory region. 149b1901de8SPhilippe Mathieu-Daudé * 150b1901de8SPhilippe Mathieu-Daudé * @qxl: QXL device 151b1901de8SPhilippe Mathieu-Daudé * @phys: physical offset of buffer within the VRAM 152b1901de8SPhilippe Mathieu-Daudé * @group_id: memory slot group 1538efec0efSPhilippe Mathieu-Daudé * @size: size of the buffer 154b1901de8SPhilippe Mathieu-Daudé * 155b1901de8SPhilippe Mathieu-Daudé * Returns a host pointer to a buffer placed at offset @phys within the 156b1901de8SPhilippe Mathieu-Daudé * active slot @group_id of the PCI VGA RAM memory region associated with 1576dbbf055SPhilippe Mathieu-Daudé * the @qxl device. If the slot is inactive, or the offset + size are out 158b1901de8SPhilippe Mathieu-Daudé * of the memory region, returns NULL. 159b1901de8SPhilippe Mathieu-Daudé * 160b1901de8SPhilippe Mathieu-Daudé * Use with care; by the time this function returns, the returned pointer is 161b1901de8SPhilippe Mathieu-Daudé * not protected by RCU anymore. If the caller is not within an RCU critical 162*a4a411fbSStefan Hajnoczi * section and does not hold the BQL, it must have other means of 163b1901de8SPhilippe Mathieu-Daudé * protecting the pointer, such as a reference to the region that includes 164b1901de8SPhilippe Mathieu-Daudé * the incoming ram_addr_t. 165b1901de8SPhilippe Mathieu-Daudé * 166b1901de8SPhilippe Mathieu-Daudé */ 1678efec0efSPhilippe Mathieu-Daudé void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id, 1688efec0efSPhilippe Mathieu-Daudé size_t size); 16947b43a1fSPaolo Bonzini void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) 1709edc6313SMarc-André Lureau G_GNUC_PRINTF(2, 3); 17147b43a1fSPaolo Bonzini 17247b43a1fSPaolo Bonzini void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, 17347b43a1fSPaolo Bonzini struct QXLRect *area, struct QXLRect *dirty_rects, 17447b43a1fSPaolo Bonzini uint32_t num_dirty_rects, 17547b43a1fSPaolo Bonzini uint32_t clear_dirty_region, 17647b43a1fSPaolo Bonzini qxl_async_io async, QXLCookie *cookie); 17747b43a1fSPaolo Bonzini void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, 17847b43a1fSPaolo Bonzini uint32_t count); 17947b43a1fSPaolo Bonzini void qxl_spice_oom(PCIQXLDevice *qxl); 18047b43a1fSPaolo Bonzini void qxl_spice_reset_memslots(PCIQXLDevice *qxl); 18147b43a1fSPaolo Bonzini void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); 18247b43a1fSPaolo Bonzini void qxl_spice_reset_cursor(PCIQXLDevice *qxl); 18347b43a1fSPaolo Bonzini 18447b43a1fSPaolo Bonzini /* qxl-logger.c */ 18547b43a1fSPaolo Bonzini int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id); 18647b43a1fSPaolo Bonzini int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); 18747b43a1fSPaolo Bonzini 18847b43a1fSPaolo Bonzini /* qxl-render.c */ 18947b43a1fSPaolo Bonzini void qxl_render_resize(PCIQXLDevice *qxl); 19047b43a1fSPaolo Bonzini void qxl_render_update(PCIQXLDevice *qxl); 19147b43a1fSPaolo Bonzini int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); 19247b43a1fSPaolo Bonzini void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie); 19347b43a1fSPaolo Bonzini void qxl_render_update_area_bh(void *opaque); 19447b43a1fSPaolo Bonzini 19547b43a1fSPaolo Bonzini #endif 196