1 #include "kvm/vesa.h" 2 3 #include "kvm/virtio-pci-dev.h" 4 #include "kvm/framebuffer.h" 5 #include "kvm/kvm-cpu.h" 6 #include "kvm/ioport.h" 7 #include "kvm/util.h" 8 #include "kvm/irq.h" 9 #include "kvm/kvm.h" 10 #include "kvm/pci.h" 11 12 #include <linux/byteorder.h> 13 #include <sys/mman.h> 14 #include <linux/err.h> 15 #include <sys/types.h> 16 #include <sys/ioctl.h> 17 #include <inttypes.h> 18 #include <unistd.h> 19 20 static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 21 { 22 return true; 23 } 24 25 static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 26 { 27 return true; 28 } 29 30 static struct ioport_operations vesa_io_ops = { 31 .io_in = vesa_pci_io_in, 32 .io_out = vesa_pci_io_out, 33 }; 34 35 static struct pci_device_header vesa_pci_device = { 36 .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), 37 .device_id = cpu_to_le16(PCI_DEVICE_ID_VESA), 38 .header_type = PCI_HEADER_TYPE_NORMAL, 39 .revision_id = 0, 40 .class[2] = 0x03, 41 .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET), 42 .subsys_id = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA), 43 .bar[1] = cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY), 44 .bar_size[1] = VESA_MEM_SIZE, 45 }; 46 47 static struct framebuffer vesafb; 48 49 struct framebuffer *vesa__init(struct kvm *kvm) 50 { 51 u16 vesa_base_addr; 52 u8 dev, line, pin; 53 char *mem; 54 int r; 55 56 r = irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line); 57 if (r < 0) 58 return ERR_PTR(r); 59 60 r = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL); 61 if (r < 0) 62 return ERR_PTR(r); 63 64 vesa_pci_device.irq_pin = pin; 65 vesa_pci_device.irq_line = line; 66 vesa_base_addr = (u16)r; 67 vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO); 68 pci__register(&vesa_pci_device, dev); 69 70 mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0); 71 if (mem == MAP_FAILED) 72 ERR_PTR(-errno); 73 74 kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem); 75 76 vesafb = (struct framebuffer) { 77 .width = VESA_WIDTH, 78 .height = VESA_HEIGHT, 79 .depth = VESA_BPP, 80 .mem = mem, 81 .mem_addr = VESA_MEM_ADDR, 82 .mem_size = VESA_MEM_SIZE, 83 .kvm = kvm, 84 }; 85 return fb__register(&vesafb); 86 } 87