1 #include "kvm/virtio-net.h" 2 #include "kvm/virtio-pci.h" 3 #include "kvm/virtio.h" 4 #include "kvm/ioport.h" 5 #include "kvm/types.h" 6 #include "kvm/mutex.h" 7 #include "kvm/util.h" 8 #include "kvm/kvm.h" 9 #include "kvm/pci.h" 10 11 #include <linux/virtio_net.h> 12 #include <linux/if_tun.h> 13 #include <net/if.h> 14 #include <sys/ioctl.h> 15 #include <assert.h> 16 #include <fcntl.h> 17 18 #define VIRTIO_NET_IRQ 14 19 #define VIRTIO_NET_QUEUE_SIZE 128 20 #define VIRTIO_NET_NUM_QUEUES 2 21 #define VIRTIO_NET_RX_QUEUE 0 22 #define VIRTIO_NET_TX_QUEUE 1 23 #define PCI_VIRTIO_NET_DEVNUM 3 24 25 struct net_device { 26 pthread_mutex_t mutex; 27 28 struct virt_queue vqs[VIRTIO_NET_NUM_QUEUES]; 29 struct virtio_net_config net_config; 30 uint32_t host_features; 31 uint32_t guest_features; 32 uint16_t config_vector; 33 uint8_t status; 34 uint16_t queue_selector; 35 36 pthread_t io_rx_thread; 37 pthread_mutex_t io_rx_mutex; 38 pthread_cond_t io_rx_cond; 39 40 pthread_t io_tx_thread; 41 pthread_mutex_t io_tx_mutex; 42 pthread_cond_t io_tx_cond; 43 44 int tap_fd; 45 char tap_name[IFNAMSIZ]; 46 }; 47 48 static struct net_device net_device = { 49 .mutex = PTHREAD_MUTEX_INITIALIZER, 50 51 .net_config = { 52 .mac = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, 53 .status = VIRTIO_NET_S_LINK_UP, 54 }, 55 56 .host_features = 1UL << VIRTIO_NET_F_MAC, 57 }; 58 59 static void *virtio_net_rx_thread(void *p) 60 { 61 struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; 62 struct virt_queue *vq; 63 struct kvm *self; 64 uint16_t out, in; 65 uint16_t head; 66 int len; 67 68 self = p; 69 vq = &net_device.vqs[VIRTIO_NET_RX_QUEUE]; 70 71 while (1) { 72 mutex_lock(&net_device.io_rx_mutex); 73 if (!virt_queue__available(vq)) 74 pthread_cond_wait(&net_device.io_rx_cond, &net_device.io_rx_mutex); 75 mutex_unlock(&net_device.io_rx_mutex); 76 77 while (virt_queue__available(vq)) { 78 head = virt_queue__get_iov(vq, iov, &out, &in, self); 79 80 /* We do not specify GSO or CSUM features, So we can ignore virtio_net_hdr */ 81 len = readv(net_device.tap_fd, iov + 1, in - 1); 82 83 /* However, We have to tell guest we have write the virtio_net_hdr */ 84 virt_queue__set_used_elem(vq, head, sizeof(struct virtio_net_hdr) + len); 85 86 /* We should interrupt guest right now, otherwise latency is huge. */ 87 kvm__irq_line(self, VIRTIO_NET_IRQ, 1); 88 } 89 90 } 91 92 pthread_exit(NULL); 93 return NULL; 94 95 } 96 97 static void *virtio_net_tx_thread(void *p) 98 { 99 struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; 100 struct virt_queue *vq; 101 struct kvm *self; 102 uint16_t out, in; 103 uint16_t head; 104 int len; 105 106 self = p; 107 vq = &net_device.vqs[VIRTIO_NET_TX_QUEUE]; 108 109 while (1) { 110 mutex_lock(&net_device.io_tx_mutex); 111 if (!virt_queue__available(vq)) 112 pthread_cond_wait(&net_device.io_tx_cond, &net_device.io_tx_mutex); 113 mutex_unlock(&net_device.io_tx_mutex); 114 115 while (virt_queue__available(vq)) { 116 head = virt_queue__get_iov(vq, iov, &out, &in, self); 117 len = writev(net_device.tap_fd, iov + 1, out - 1); 118 virt_queue__set_used_elem(vq, head, len); 119 } 120 121 kvm__irq_line(self, VIRTIO_NET_IRQ, 1); 122 } 123 124 pthread_exit(NULL); 125 return NULL; 126 127 } 128 static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offset, int size, uint32_t count) 129 { 130 uint8_t *config_space = (uint8_t *) &net_device.net_config; 131 132 if (size != 1 || count != 1) 133 return false; 134 135 if ((offset - VIRTIO_PCI_CONFIG_NOMSI) > sizeof(struct virtio_net_config)) 136 error("config offset is too big: %li", offset - VIRTIO_PCI_CONFIG_NOMSI); 137 138 ioport__write8(data, config_space[offset - VIRTIO_PCI_CONFIG_NOMSI]); 139 140 return true; 141 } 142 143 static bool virtio_net_pci_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 144 { 145 unsigned long offset = port - IOPORT_VIRTIO_NET; 146 bool ret = true; 147 148 mutex_lock(&net_device.mutex); 149 150 switch (offset) { 151 case VIRTIO_PCI_HOST_FEATURES: 152 ioport__write32(data, net_device.host_features); 153 break; 154 case VIRTIO_PCI_GUEST_FEATURES: 155 ret = false; 156 break; 157 case VIRTIO_PCI_QUEUE_PFN: 158 ioport__write32(data, net_device.vqs[net_device.queue_selector].pfn); 159 break; 160 case VIRTIO_PCI_QUEUE_NUM: 161 ioport__write16(data, VIRTIO_NET_QUEUE_SIZE); 162 break; 163 case VIRTIO_PCI_QUEUE_SEL: 164 case VIRTIO_PCI_QUEUE_NOTIFY: 165 ret = false; 166 break; 167 case VIRTIO_PCI_STATUS: 168 ioport__write8(data, net_device.status); 169 break; 170 case VIRTIO_PCI_ISR: 171 ioport__write8(data, 0x1); 172 kvm__irq_line(self, VIRTIO_NET_IRQ, 0); 173 break; 174 case VIRTIO_MSI_CONFIG_VECTOR: 175 ioport__write16(data, net_device.config_vector); 176 break; 177 default: 178 ret = virtio_net_pci_io_device_specific_in(data, offset, size, count); 179 }; 180 181 mutex_unlock(&net_device.mutex); 182 183 return ret; 184 } 185 186 static void virtio_net_handle_callback(struct kvm *self, uint16_t queue_index) 187 { 188 if (queue_index == VIRTIO_NET_TX_QUEUE) { 189 190 mutex_lock(&net_device.io_tx_mutex); 191 pthread_cond_signal(&net_device.io_tx_cond); 192 mutex_unlock(&net_device.io_tx_mutex); 193 194 } else if (queue_index == VIRTIO_NET_RX_QUEUE) { 195 196 mutex_lock(&net_device.io_rx_mutex); 197 pthread_cond_signal(&net_device.io_rx_cond); 198 mutex_unlock(&net_device.io_rx_mutex); 199 200 } 201 } 202 203 static bool virtio_net_pci_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 204 { 205 unsigned long offset = port - IOPORT_VIRTIO_NET; 206 bool ret = true; 207 208 mutex_lock(&net_device.mutex); 209 210 switch (offset) { 211 case VIRTIO_PCI_GUEST_FEATURES: 212 net_device.guest_features = ioport__read32(data); 213 break; 214 case VIRTIO_PCI_QUEUE_PFN: { 215 struct virt_queue *queue; 216 void *p; 217 218 assert(net_device.queue_selector < VIRTIO_NET_NUM_QUEUES); 219 220 queue = &net_device.vqs[net_device.queue_selector]; 221 queue->pfn = ioport__read32(data); 222 p = guest_flat_to_host(self, queue->pfn << 12); 223 224 vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, 4096); 225 226 break; 227 } 228 case VIRTIO_PCI_QUEUE_SEL: 229 net_device.queue_selector = ioport__read16(data); 230 break; 231 case VIRTIO_PCI_QUEUE_NOTIFY: { 232 uint16_t queue_index; 233 queue_index = ioport__read16(data); 234 virtio_net_handle_callback(self, queue_index); 235 break; 236 } 237 case VIRTIO_PCI_STATUS: 238 net_device.status = ioport__read8(data); 239 break; 240 case VIRTIO_MSI_CONFIG_VECTOR: 241 net_device.config_vector = VIRTIO_MSI_NO_VECTOR; 242 break; 243 case VIRTIO_MSI_QUEUE_VECTOR: 244 break; 245 default: 246 ret = false; 247 }; 248 249 mutex_unlock(&net_device.mutex); 250 return ret; 251 } 252 253 static struct ioport_operations virtio_net_io_ops = { 254 .io_in = virtio_net_pci_io_in, 255 .io_out = virtio_net_pci_io_out, 256 }; 257 258 #define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 259 #define PCI_DEVICE_ID_VIRTIO_NET 0x1000 260 #define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4 261 #define PCI_SUBSYSTEM_ID_VIRTIO_NET 0x0001 262 263 static struct pci_device_header virtio_net_pci_device = { 264 .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, 265 .device_id = PCI_DEVICE_ID_VIRTIO_NET, 266 .header_type = PCI_HEADER_TYPE_NORMAL, 267 .revision_id = 0, 268 .class = 0x020000, 269 .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET, 270 .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_NET, 271 .bar[0] = IOPORT_VIRTIO_NET | PCI_BASE_ADDRESS_SPACE_IO, 272 .irq_pin = 3, 273 .irq_line = VIRTIO_NET_IRQ, 274 }; 275 276 static void virtio_net__tap_init(void) 277 { 278 struct ifreq ifr; 279 280 net_device.tap_fd = open("/dev/net/tun", O_RDWR); 281 if (net_device.tap_fd < 0) 282 die("Unable to open /dev/net/tun\n"); 283 284 memset(&ifr, 0, sizeof(ifr)); 285 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 286 287 if (ioctl(net_device.tap_fd, TUNSETIFF, &ifr) < 0) 288 die("Config tap device error. Are you root?"); 289 290 strncpy(net_device.tap_name, ifr.ifr_name, sizeof(net_device.tap_name)); 291 292 ioctl(net_device.tap_fd, TUNSETNOCSUM, 1); 293 294 /*FIXME: Remove this after user can specify ip address and netmask*/ 295 if (system("ifconfig tap0 192.168.33.2") < 0) 296 warning("Can not set ip address on tap0"); 297 } 298 299 static void virtio_net__io_thread_init(struct kvm *self) 300 { 301 pthread_mutex_init(&net_device.io_rx_mutex, NULL); 302 pthread_cond_init(&net_device.io_tx_cond, NULL); 303 304 pthread_mutex_init(&net_device.io_rx_mutex, NULL); 305 pthread_cond_init(&net_device.io_tx_cond, NULL); 306 307 pthread_create(&net_device.io_rx_thread, NULL, virtio_net_rx_thread, (void *)self); 308 pthread_create(&net_device.io_tx_thread, NULL, virtio_net_tx_thread, (void *)self); 309 } 310 311 void virtio_net__init(struct kvm *self) 312 { 313 pci__register(&virtio_net_pci_device, PCI_VIRTIO_NET_DEVNUM); 314 ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE); 315 316 virtio_net__tap_init(); 317 virtio_net__io_thread_init(self); 318 } 319