1 #include "kvm/vesa.h"
2
3 #include "kvm/devices.h"
4 #include "kvm/virtio-pci-dev.h"
5 #include "kvm/framebuffer.h"
6 #include "kvm/kvm-cpu.h"
7 #include "kvm/ioport.h"
8 #include "kvm/util.h"
9 #include "kvm/irq.h"
10 #include "kvm/kvm.h"
11 #include "kvm/pci.h"
12
13 #include <linux/byteorder.h>
14 #include <sys/mman.h>
15 #include <linux/err.h>
16 #include <sys/types.h>
17 #include <sys/ioctl.h>
18 #include <inttypes.h>
19 #include <unistd.h>
20
21 static struct pci_device_header vesa_pci_device = {
22 .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
23 .device_id = cpu_to_le16(PCI_DEVICE_ID_VESA),
24 .header_type = PCI_HEADER_TYPE_NORMAL,
25 .revision_id = 0,
26 .class[2] = 0x03,
27 .subsys_vendor_id = cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
28 .subsys_id = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
29 .bar[1] = cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
30 .bar_size[1] = VESA_MEM_SIZE,
31 };
32
33 static struct device_header vesa_device = {
34 .bus_type = DEVICE_BUS_PCI,
35 .data = &vesa_pci_device,
36 };
37
38 static struct framebuffer vesafb = {
39 .width = VESA_WIDTH,
40 .height = VESA_HEIGHT,
41 .depth = VESA_BPP,
42 .mem_addr = VESA_MEM_ADDR,
43 .mem_size = VESA_MEM_SIZE,
44 };
45
vesa_pci_io(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * ptr)46 static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
47 u8 is_write, void *ptr)
48 {
49 }
50
vesa__bar_activate(struct kvm * kvm,struct pci_device_header * pci_hdr,int bar_num,void * data)51 static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header *pci_hdr,
52 int bar_num, void *data)
53 {
54 /* We don't support remapping of the framebuffer. */
55 return 0;
56 }
57
vesa__bar_deactivate(struct kvm * kvm,struct pci_device_header * pci_hdr,int bar_num,void * data)58 static int vesa__bar_deactivate(struct kvm *kvm, struct pci_device_header *pci_hdr,
59 int bar_num, void *data)
60 {
61 /* We don't support remapping of the framebuffer. */
62 return -EINVAL;
63 }
64
vesa__init(struct kvm * kvm)65 struct framebuffer *vesa__init(struct kvm *kvm)
66 {
67 u16 vesa_base_addr;
68 char *mem;
69 int r;
70
71 BUILD_BUG_ON(!is_power_of_two(VESA_MEM_SIZE));
72 BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT);
73
74 vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE);
75 r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io,
76 NULL);
77 if (r < 0)
78 goto out_error;
79
80 vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
81 vesa_pci_device.bar_size[0] = PCI_IO_SIZE;
82 r = pci__register_bar_regions(kvm, &vesa_pci_device, vesa__bar_activate,
83 vesa__bar_deactivate, NULL);
84 if (r < 0)
85 goto unregister_ioport;
86
87 r = device__register(&vesa_device);
88 if (r < 0)
89 goto unregister_ioport;
90
91 mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
92 if (mem == MAP_FAILED) {
93 r = -errno;
94 goto unregister_device;
95 }
96
97 r = kvm__register_dev_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem);
98 if (r < 0)
99 goto unmap_dev;
100
101 vesafb.mem = mem;
102 vesafb.kvm = kvm;
103 return fb__register(&vesafb);
104
105 unmap_dev:
106 munmap(mem, VESA_MEM_SIZE);
107 unregister_device:
108 device__unregister(&vesa_device);
109 unregister_ioport:
110 kvm__deregister_pio(kvm, vesa_base_addr);
111 out_error:
112 return ERR_PTR(r);
113 }
114