1*9bd8ac5cSAsias He #include "kvm/console-virtio.h" 2*9bd8ac5cSAsias He #include "kvm/virtio_pci.h" 3*9bd8ac5cSAsias He #include "kvm/disk-image.h" 4*9bd8ac5cSAsias He #include "kvm/virtqueue.h" 5*9bd8ac5cSAsias He #include "kvm/ioport.h" 6*9bd8ac5cSAsias He #include "kvm/util.h" 7*9bd8ac5cSAsias He #include "kvm/term.h" 8*9bd8ac5cSAsias He #include "kvm/kvm.h" 9*9bd8ac5cSAsias He #include "kvm/pci.h" 10*9bd8ac5cSAsias He 11*9bd8ac5cSAsias He #include <linux/virtio_console.h> 12*9bd8ac5cSAsias He #include <linux/virtio_ring.h> 13*9bd8ac5cSAsias He #include <linux/virtio_blk.h> 14*9bd8ac5cSAsias He 15*9bd8ac5cSAsias He #include <sys/uio.h> 16*9bd8ac5cSAsias He #include <sys/types.h> 17*9bd8ac5cSAsias He #include <sys/stat.h> 18*9bd8ac5cSAsias He #include <inttypes.h> 19*9bd8ac5cSAsias He #include <termios.h> 20*9bd8ac5cSAsias He #include <assert.h> 21*9bd8ac5cSAsias He #include <unistd.h> 22*9bd8ac5cSAsias He #include <fcntl.h> 23*9bd8ac5cSAsias He 24*9bd8ac5cSAsias He #define VIRTIO_CONSOLE_IRQ 14 25*9bd8ac5cSAsias He #define VIRTIO_CONSOLE_QUEUE_SIZE 128 26*9bd8ac5cSAsias He #define VIRTIO_CONSOLE_NUM_QUEUES 2 27*9bd8ac5cSAsias He #define VIRTIO_CONSOLE_RX_QUEUE 0 28*9bd8ac5cSAsias He #define VIRTIO_CONSOLE_TX_QUEUE 1 29*9bd8ac5cSAsias He #define PCI_VIRTIO_CONSOLE_DEVNUM 2 30*9bd8ac5cSAsias He 31*9bd8ac5cSAsias He struct console_device { 32*9bd8ac5cSAsias He struct virt_queue vqs[VIRTIO_CONSOLE_NUM_QUEUES]; 33*9bd8ac5cSAsias He struct virtio_console_config console_config; 34*9bd8ac5cSAsias He uint32_t host_features; 35*9bd8ac5cSAsias He uint32_t guest_features; 36*9bd8ac5cSAsias He uint16_t config_vector; 37*9bd8ac5cSAsias He uint8_t status; 38*9bd8ac5cSAsias He uint16_t queue_selector; 39*9bd8ac5cSAsias He }; 40*9bd8ac5cSAsias He 41*9bd8ac5cSAsias He static struct console_device console_device = { 42*9bd8ac5cSAsias He .console_config = { 43*9bd8ac5cSAsias He .cols = 80, 44*9bd8ac5cSAsias He .rows = 24, 45*9bd8ac5cSAsias He .max_nr_ports = 1, 46*9bd8ac5cSAsias He }, 47*9bd8ac5cSAsias He 48*9bd8ac5cSAsias He .host_features = 0, 49*9bd8ac5cSAsias He }; 50*9bd8ac5cSAsias He 51*9bd8ac5cSAsias He /* 52*9bd8ac5cSAsias He * Interrupts are injected for hvc0 only. 53*9bd8ac5cSAsias He */ 54*9bd8ac5cSAsias He void virtio_console__inject_interrupt(struct kvm *self) 55*9bd8ac5cSAsias He { 56*9bd8ac5cSAsias He struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE]; 57*9bd8ac5cSAsias He struct virt_queue *vq; 58*9bd8ac5cSAsias He uint16_t out, in; 59*9bd8ac5cSAsias He uint16_t head; 60*9bd8ac5cSAsias He int len; 61*9bd8ac5cSAsias He 62*9bd8ac5cSAsias He vq = &console_device.vqs[VIRTIO_CONSOLE_RX_QUEUE]; 63*9bd8ac5cSAsias He 64*9bd8ac5cSAsias He if (term_readable(CONSOLE_VIRTIO) && virt_queue__available(vq)) { 65*9bd8ac5cSAsias He head = virt_queue__get_iov(vq, iov, &out, &in, self); 66*9bd8ac5cSAsias He len = term_getc_iov(CONSOLE_VIRTIO, iov, in); 67*9bd8ac5cSAsias He virt_queue__set_used_elem(vq, head, len); 68*9bd8ac5cSAsias He kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1); 69*9bd8ac5cSAsias He } 70*9bd8ac5cSAsias He } 71*9bd8ac5cSAsias He 72*9bd8ac5cSAsias He static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count) 73*9bd8ac5cSAsias He { 74*9bd8ac5cSAsias He uint8_t *config_space = (uint8_t *) &console_device.console_config; 75*9bd8ac5cSAsias He 76*9bd8ac5cSAsias He if (size != 1 || count != 1) 77*9bd8ac5cSAsias He return false; 78*9bd8ac5cSAsias He 79*9bd8ac5cSAsias He if ((offset - VIRTIO_PCI_CONFIG_NOMSI) > sizeof(struct virtio_console_config)) 80*9bd8ac5cSAsias He error("config offset is too big: %li", offset - VIRTIO_PCI_CONFIG_NOMSI); 81*9bd8ac5cSAsias He 82*9bd8ac5cSAsias He ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]); 83*9bd8ac5cSAsias He 84*9bd8ac5cSAsias He return true; 85*9bd8ac5cSAsias He } 86*9bd8ac5cSAsias He 87*9bd8ac5cSAsias He static bool virtio_console_pci_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 88*9bd8ac5cSAsias He { 89*9bd8ac5cSAsias He unsigned long offset = port - IOPORT_VIRTIO_CONSOLE; 90*9bd8ac5cSAsias He 91*9bd8ac5cSAsias He switch (offset) { 92*9bd8ac5cSAsias He case VIRTIO_PCI_HOST_FEATURES: 93*9bd8ac5cSAsias He ioport__write32(data, console_device.host_features); 94*9bd8ac5cSAsias He break; 95*9bd8ac5cSAsias He case VIRTIO_PCI_GUEST_FEATURES: 96*9bd8ac5cSAsias He return false; 97*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_PFN: 98*9bd8ac5cSAsias He ioport__write32(data, console_device.vqs[console_device.queue_selector].pfn); 99*9bd8ac5cSAsias He break; 100*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_NUM: 101*9bd8ac5cSAsias He ioport__write16(data, VIRTIO_CONSOLE_QUEUE_SIZE); 102*9bd8ac5cSAsias He break; 103*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_SEL: 104*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_NOTIFY: 105*9bd8ac5cSAsias He return false; 106*9bd8ac5cSAsias He case VIRTIO_PCI_STATUS: 107*9bd8ac5cSAsias He ioport__write8(data, console_device.status); 108*9bd8ac5cSAsias He break; 109*9bd8ac5cSAsias He case VIRTIO_PCI_ISR: 110*9bd8ac5cSAsias He ioport__write8(data, 0x1); 111*9bd8ac5cSAsias He kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 0); 112*9bd8ac5cSAsias He break; 113*9bd8ac5cSAsias He case VIRTIO_MSI_CONFIG_VECTOR: 114*9bd8ac5cSAsias He ioport__write16(data, console_device.config_vector); 115*9bd8ac5cSAsias He break; 116*9bd8ac5cSAsias He default: 117*9bd8ac5cSAsias He return virtio_console_pci_io_device_specific_in(data, offset, size, count); 118*9bd8ac5cSAsias He }; 119*9bd8ac5cSAsias He 120*9bd8ac5cSAsias He return true; 121*9bd8ac5cSAsias He } 122*9bd8ac5cSAsias He 123*9bd8ac5cSAsias He static void virtio_console_handle_callback(struct kvm *self, uint16_t queue_index) 124*9bd8ac5cSAsias He { 125*9bd8ac5cSAsias He struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE]; 126*9bd8ac5cSAsias He struct virt_queue *vq; 127*9bd8ac5cSAsias He uint16_t out, in; 128*9bd8ac5cSAsias He uint16_t head; 129*9bd8ac5cSAsias He uint32_t len; 130*9bd8ac5cSAsias He 131*9bd8ac5cSAsias He vq = &console_device.vqs[queue_index]; 132*9bd8ac5cSAsias He 133*9bd8ac5cSAsias He if (queue_index == VIRTIO_CONSOLE_TX_QUEUE) { 134*9bd8ac5cSAsias He 135*9bd8ac5cSAsias He while (virt_queue__available(vq)) { 136*9bd8ac5cSAsias He head = virt_queue__get_iov(vq, iov, &out, &in, self); 137*9bd8ac5cSAsias He len = term_putc_iov(CONSOLE_VIRTIO, iov, out); 138*9bd8ac5cSAsias He virt_queue__set_used_elem(vq, head, len); 139*9bd8ac5cSAsias He } 140*9bd8ac5cSAsias He 141*9bd8ac5cSAsias He kvm__irq_line(self, VIRTIO_CONSOLE_IRQ, 1); 142*9bd8ac5cSAsias He } 143*9bd8ac5cSAsias He } 144*9bd8ac5cSAsias He 145*9bd8ac5cSAsias He static bool virtio_console_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 146*9bd8ac5cSAsias He { 147*9bd8ac5cSAsias He unsigned long offset = port - IOPORT_VIRTIO_CONSOLE; 148*9bd8ac5cSAsias He 149*9bd8ac5cSAsias He switch (offset) { 150*9bd8ac5cSAsias He case VIRTIO_PCI_GUEST_FEATURES: 151*9bd8ac5cSAsias He console_device.guest_features = ioport__read32(data); 152*9bd8ac5cSAsias He break; 153*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_PFN: { 154*9bd8ac5cSAsias He struct virt_queue *queue; 155*9bd8ac5cSAsias He void *p; 156*9bd8ac5cSAsias He 157*9bd8ac5cSAsias He assert(console_device.queue_selector < VIRTIO_CONSOLE_NUM_QUEUES); 158*9bd8ac5cSAsias He 159*9bd8ac5cSAsias He queue = &console_device.vqs[console_device.queue_selector]; 160*9bd8ac5cSAsias He queue->pfn = ioport__read32(data); 161*9bd8ac5cSAsias He p = guest_flat_to_host(self, queue->pfn << 12); 162*9bd8ac5cSAsias He 163*9bd8ac5cSAsias He vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, 4096); 164*9bd8ac5cSAsias He 165*9bd8ac5cSAsias He break; 166*9bd8ac5cSAsias He } 167*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_SEL: 168*9bd8ac5cSAsias He console_device.queue_selector = ioport__read16(data); 169*9bd8ac5cSAsias He break; 170*9bd8ac5cSAsias He case VIRTIO_PCI_QUEUE_NOTIFY: { 171*9bd8ac5cSAsias He uint16_t queue_index; 172*9bd8ac5cSAsias He queue_index = ioport__read16(data); 173*9bd8ac5cSAsias He virtio_console_handle_callback(self, queue_index); 174*9bd8ac5cSAsias He break; 175*9bd8ac5cSAsias He } 176*9bd8ac5cSAsias He case VIRTIO_PCI_STATUS: 177*9bd8ac5cSAsias He console_device.status = ioport__read8(data); 178*9bd8ac5cSAsias He break; 179*9bd8ac5cSAsias He case VIRTIO_MSI_CONFIG_VECTOR: 180*9bd8ac5cSAsias He console_device.config_vector = VIRTIO_MSI_NO_VECTOR; 181*9bd8ac5cSAsias He break; 182*9bd8ac5cSAsias He case VIRTIO_MSI_QUEUE_VECTOR: 183*9bd8ac5cSAsias He break; 184*9bd8ac5cSAsias He default: 185*9bd8ac5cSAsias He return false; 186*9bd8ac5cSAsias He }; 187*9bd8ac5cSAsias He 188*9bd8ac5cSAsias He return true; 189*9bd8ac5cSAsias He } 190*9bd8ac5cSAsias He 191*9bd8ac5cSAsias He static struct ioport_operations virtio_console_io_ops = { 192*9bd8ac5cSAsias He .io_in = virtio_console_pci_io_in, 193*9bd8ac5cSAsias He .io_out = virtio_console_pci_io_out, 194*9bd8ac5cSAsias He }; 195*9bd8ac5cSAsias He 196*9bd8ac5cSAsias He #define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 197*9bd8ac5cSAsias He #define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1002 198*9bd8ac5cSAsias He #define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4 199*9bd8ac5cSAsias He #define PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE 0x0003 200*9bd8ac5cSAsias He 201*9bd8ac5cSAsias He static struct pci_device_header virtio_console_pci_device = { 202*9bd8ac5cSAsias He .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, 203*9bd8ac5cSAsias He .device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE, 204*9bd8ac5cSAsias He .header_type = PCI_HEADER_TYPE_NORMAL, 205*9bd8ac5cSAsias He .revision_id = 0, 206*9bd8ac5cSAsias He .class = (0x07 << 8) | (0x80 << 4) | (0x0 << 0), 207*9bd8ac5cSAsias He .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET, 208*9bd8ac5cSAsias He .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_CONSOLE, 209*9bd8ac5cSAsias He .bar[0] = IOPORT_VIRTIO_CONSOLE | PCI_BASE_ADDRESS_SPACE_IO, 210*9bd8ac5cSAsias He .irq_pin = 3, 211*9bd8ac5cSAsias He .irq_line = VIRTIO_CONSOLE_IRQ, 212*9bd8ac5cSAsias He }; 213*9bd8ac5cSAsias He 214*9bd8ac5cSAsias He void virtio_console__init(struct kvm *self) 215*9bd8ac5cSAsias He { 216*9bd8ac5cSAsias He pci__register(&virtio_console_pci_device, PCI_VIRTIO_CONSOLE_DEVNUM); 217*9bd8ac5cSAsias He ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE); 218*9bd8ac5cSAsias He } 219