#include "kvm/vesa.h" #include "kvm/devices.h" #include "kvm/virtio-pci-dev.h" #include "kvm/framebuffer.h" #include "kvm/kvm-cpu.h" #include "kvm/ioport.h" #include "kvm/util.h" #include "kvm/irq.h" #include "kvm/kvm.h" #include "kvm/pci.h" #include #include #include #include #include #include #include static struct pci_device_header vesa_pci_device = { .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), .device_id = cpu_to_le16(PCI_DEVICE_ID_VESA), .header_type = PCI_HEADER_TYPE_NORMAL, .revision_id = 0, .class[2] = 0x03, .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET), .subsys_id = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA), .bar[1] = cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY), .bar_size[1] = VESA_MEM_SIZE, }; static struct device_header vesa_device = { .bus_type = DEVICE_BUS_PCI, .data = &vesa_pci_device, }; static struct framebuffer vesafb = { .width = VESA_WIDTH, .height = VESA_HEIGHT, .depth = VESA_BPP, .mem_addr = VESA_MEM_ADDR, .mem_size = VESA_MEM_SIZE, }; static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len, u8 is_write, void *ptr) { } static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header *pci_hdr, int bar_num, void *data) { /* We don't support remapping of the framebuffer. */ return 0; } static int vesa__bar_deactivate(struct kvm *kvm, struct pci_device_header *pci_hdr, int bar_num, void *data) { /* We don't support remapping of the framebuffer. */ return -EINVAL; } struct framebuffer *vesa__init(struct kvm *kvm) { u16 vesa_base_addr; char *mem; int r; BUILD_BUG_ON(!is_power_of_two(VESA_MEM_SIZE)); BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT); vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE); r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io, NULL); if (r < 0) goto out_error; vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO); vesa_pci_device.bar_size[0] = PCI_IO_SIZE; r = pci__register_bar_regions(kvm, &vesa_pci_device, vesa__bar_activate, vesa__bar_deactivate, NULL); if (r < 0) goto unregister_ioport; r = device__register(&vesa_device); if (r < 0) goto unregister_ioport; mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0); if (mem == MAP_FAILED) { r = -errno; goto unregister_device; } r = kvm__register_dev_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem); if (r < 0) goto unmap_dev; vesafb.mem = mem; vesafb.kvm = kvm; return fb__register(&vesafb); unmap_dev: munmap(mem, VESA_MEM_SIZE); unregister_device: device__unregister(&vesa_device); unregister_ioport: kvm__deregister_pio(kvm, vesa_base_addr); out_error: return ERR_PTR(r); }