Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


0059fb6f8fa6b6eb93b3f70aebd5a9dc4d99f0a0
[palacios.git] / palacios / src / devices / lnx_virtio_blk.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_dev_mgr.h>
22 #include <devices/lnx_virtio_pci.h>
23 #include <devices/lnx_virtio_blk.h>
24 #include <devices/block_dev.h>
25 #include <palacios/vm_guest_mem.h>
26
27 #include <devices/pci.h>
28
29
30
31 #ifndef CONFIG_DEBUG_VIRTIO_BLK
32 #undef PrintDebug
33 #define PrintDebug(fmt, args...)
34 #endif
35
36
37 #define BLK_CAPACITY_PORT     20
38 #define BLK_MAX_SIZE_PORT     28
39 #define BLK_MAX_SEG_PORT      32
40 #define BLK_CYLINDERS_PORT    36
41 #define BLK_HEADS_PORT        38
42 #define BLK_SECTS_PORT        39
43
44 #define BLK_IN_REQ            0
45 #define BLK_OUT_REQ           1
46 #define BLK_SCSI_CMD          2
47
48 #define BLK_BARRIER_FLAG     0x80000000
49
50 #define BLK_STATUS_OK             0
51 #define BLK_STATUS_ERR            1
52 #define BLK_STATUS_NOT_SUPPORTED  2
53
54
55 struct blk_config {
56     uint64_t capacity;
57     uint32_t max_size;
58     uint32_t max_seg;
59     uint16_t cylinders;
60     uint8_t heads;
61     uint8_t sectors;
62 } __attribute__((packed));
63
64
65
66 struct blk_op_hdr {
67     uint32_t type;
68     uint32_t prior;
69     uint64_t sector;
70 } __attribute__((packed));
71
72 #define QUEUE_SIZE 128
73
74 /* Host Feature flags */
75 #define VIRTIO_BARRIER       0x01       /* Does host support barriers? */
76 #define VIRTIO_SIZE_MAX      0x02       /* Indicates maximum segment size */
77 #define VIRTIO_SEG_MAX       0x04       /* Indicates maximum # of segments */
78 #define VIRTIO_LEGACY_GEOM   0x10       /* Indicates support of legacy geometry */
79
80
81
82
83 struct virtio_blk_state {
84     struct blk_config block_cfg;
85     struct virtio_config virtio_cfg;
86
87     struct vm_device * pci_bus;
88     struct pci_device * pci_dev;
89     
90     struct virtio_queue queue;
91
92     union {
93         struct v3_cd_ops * cd_ops;
94         struct v3_hd_ops * hd_ops;
95     };
96
97     v3_block_type_t block_type;
98     void * backend_data;
99
100     int io_range_size;
101 };
102
103
104 static int virtio_free(struct vm_device * dev) {
105     return -1;
106 }
107
108 static int virtio_reset(struct vm_device * dev) {
109     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
110
111     virtio->queue.ring_desc_addr = 0;
112     virtio->queue.ring_avail_addr = 0;
113     virtio->queue.ring_used_addr = 0;
114     virtio->queue.pfn = 0;
115     virtio->queue.cur_avail_idx = 0;
116
117     virtio->virtio_cfg.status = 0;
118     virtio->virtio_cfg.pci_isr = 0;
119
120     return 0;
121 }
122
123 static int handle_read_op(struct vm_device * dev, uint8_t * buf, uint64_t * sector, uint32_t len) {
124     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data; 
125     int ret = -1;
126
127     if (virtio->block_type == BLOCK_DISK) {
128         if (len % HD_SECTOR_SIZE) {
129             PrintError("Write of something that is not a sector len %d, mod=%d\n", len, len % HD_SECTOR_SIZE);
130             return -1;
131         }
132
133
134         PrintDebug("Reading Disk\n");
135             
136         ret = virtio->hd_ops->read(buf, len / HD_SECTOR_SIZE, *sector, virtio->backend_data);
137
138         *sector += len / HD_SECTOR_SIZE;
139
140     } else if (virtio->block_type == BLOCK_CDROM) {
141         if (len % ATAPI_BLOCK_SIZE) {
142             PrintError("Write of something that is not an ATAPI block len %d, mod=%d\n", len, len % ATAPI_BLOCK_SIZE);
143             return -1;
144         }
145
146         ret = virtio->cd_ops->read(buf, len / ATAPI_BLOCK_SIZE, *sector , virtio->backend_data);
147
148         *sector += len / ATAPI_BLOCK_SIZE;
149     }
150
151     return ret;
152 }
153
154
155 static int handle_write_op(struct vm_device * dev, uint8_t * buf, uint64_t * sector, uint32_t len) {
156     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data; 
157     int ret = -1;
158
159     if (virtio->block_type == BLOCK_DISK) {
160         if (len % HD_SECTOR_SIZE) {
161             PrintError("Write of something that is not a sector len %d, mod=%d\n", len, len % HD_SECTOR_SIZE);
162             return -1;
163         }
164
165         PrintDebug("Writing Disk\n");
166
167         ret = virtio->hd_ops->write(buf, len / HD_SECTOR_SIZE, *sector, virtio->backend_data);
168
169         *sector += len / HD_SECTOR_SIZE;        
170     }
171
172     return ret;
173 }
174
175
176
177 // multiple block operations need to increment the sector 
178
179 static int handle_block_op(struct vm_device * dev, struct blk_op_hdr * hdr, 
180                            struct vring_desc * buf_desc, uint8_t * status) {
181     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
182     uint8_t * buf = NULL;
183
184     PrintDebug("Handling Block op\n");
185
186
187
188     if (guest_pa_to_host_va(dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
189         PrintError("Could not translate buffer address\n");
190         return -1;
191     }
192
193
194     PrintDebug("Sector=%p Length=%d\n", (void *)(addr_t)(hdr->sector), buf_desc->length);
195
196     if (hdr->type == BLK_IN_REQ) {
197         if (virtio->block_type != BLOCK_NONE) {
198             if (handle_read_op(dev, buf, &(hdr->sector), buf_desc->length) == -1) {
199                 *status = BLK_STATUS_ERR;
200                 return -1;
201             } else {
202                 *status = BLK_STATUS_OK;
203             }
204         } else {
205             *status = BLK_STATUS_NOT_SUPPORTED;
206         }
207
208     } else if (hdr->type == BLK_OUT_REQ) {
209         if (virtio->block_type == BLOCK_DISK) {
210             if (handle_write_op(dev, buf, &(hdr->sector), buf_desc->length) == -1) {
211                 *status = BLK_STATUS_ERR;
212                 return -1;
213             } else {
214                 *status = BLK_STATUS_OK;
215             }
216
217         } else {
218             *status = BLK_STATUS_NOT_SUPPORTED;
219         }
220
221     } else if (hdr->type == BLK_SCSI_CMD) {
222         PrintError("VIRTIO: SCSI Command Not supported!!!\n");
223         *status = BLK_STATUS_NOT_SUPPORTED;
224         return -1;
225     }
226
227
228
229     PrintDebug("Returning Status: %d\n", *status);
230
231     return 0;
232 }
233
234 static int get_desc_count(struct virtio_queue * q, int index) {
235     struct vring_desc * tmp_desc = &(q->desc[index]);
236     int cnt = 1;
237     
238     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
239         tmp_desc = &(q->desc[tmp_desc->next]);
240         cnt++;
241     }
242
243     return cnt;
244 }
245
246
247
248 static int handle_kick(struct vm_device * dev) {
249     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
250     struct virtio_queue * q = &(virtio->queue);
251
252     PrintDebug("VIRTIO KICK: cur_index=%d (mod=%d), avail_index=%d\n", 
253                q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
254
255     while (q->cur_avail_idx < q->avail->index) {
256         struct vring_desc * hdr_desc = NULL;
257         struct vring_desc * buf_desc = NULL;
258         struct vring_desc * status_desc = NULL;
259         struct blk_op_hdr hdr;
260         addr_t hdr_addr = 0;
261         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
262         int desc_cnt = get_desc_count(q, desc_idx);
263         int i = 0;
264         uint8_t * status_ptr = NULL;
265         uint8_t status = BLK_STATUS_OK;
266         uint32_t req_len = 0;
267
268         PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
269
270         if (desc_cnt < 3) {
271             PrintError("Block operations must include at least 3 descriptors\n");
272             return -1;
273         }
274
275         hdr_desc = &(q->desc[desc_idx]);
276
277
278         PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
279                    (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
280
281         if (guest_pa_to_host_va(dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
282             PrintError("Could not translate block header address\n");
283             return -1;
284         }
285
286         // We copy the block op header out because we are going to modify its contents
287         memcpy(&hdr, (void *)hdr_addr, sizeof(struct blk_op_hdr));
288         
289         PrintDebug("Blk Op Hdr (ptr=%p) type=%d, sector=%p\n", (void *)hdr_addr, hdr.type, (void *)hdr.sector);
290
291         desc_idx = hdr_desc->next;
292
293         for (i = 0; i < desc_cnt - 2; i++) {
294             uint8_t tmp_status = BLK_STATUS_OK;
295
296             buf_desc = &(q->desc[desc_idx]);
297
298             PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
299                        (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
300
301             if (handle_block_op(dev, &hdr, buf_desc, &tmp_status) == -1) {
302                 PrintError("Error handling block operation\n");
303                 return -1;
304             }
305
306             if (tmp_status != BLK_STATUS_OK) {
307                 status = tmp_status;
308             }
309
310             req_len += buf_desc->length;
311             desc_idx = buf_desc->next;
312         }
313
314         status_desc = &(q->desc[desc_idx]);
315
316         PrintDebug("Status Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", status_desc, 
317                    (void *)(status_desc->addr_gpa), status_desc->length, status_desc->flags, status_desc->next);
318
319         if (guest_pa_to_host_va(dev->vm, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) {
320             PrintError("Could not translate status address\n");
321             return -1;
322         }
323
324         req_len += status_desc->length;
325         *status_ptr = status;
326
327         q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
328         q->used->ring[q->used->index % QUEUE_SIZE].length = req_len; // What do we set this to????
329
330         q->used->index++;
331         q->cur_avail_idx++;
332     }
333
334     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
335         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
336         v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
337         virtio->virtio_cfg.pci_isr = 1;
338     }
339
340     return 0;
341 }
342
343 static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) {
344     struct vm_device * dev = (struct vm_device *)private_data;
345     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
346     int port_idx = port % virtio->io_range_size;
347
348
349     PrintDebug("VIRTIO BLOCK Write for port %d (index=%d) len=%d, value=%x\n", 
350                port, port_idx,  length, *(uint32_t *)src);
351
352
353
354     switch (port_idx) {
355         case GUEST_FEATURES_PORT:
356             if (length != 4) {
357                 PrintError("Illegal write length for guest features\n");
358                 return -1;
359             }
360             
361             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
362             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
363
364             break;
365         case VRING_PG_NUM_PORT:
366             if (length == 4) {
367                 addr_t pfn = *(uint32_t *)src;
368                 addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
369
370
371                 virtio->queue.pfn = pfn;
372                 
373                 virtio->queue.ring_desc_addr = page_addr ;
374                 virtio->queue.ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
375                 virtio->queue.ring_used_addr = ( virtio->queue.ring_avail_addr + \
376                                                  sizeof(struct vring_avail)    + \
377                                                  (QUEUE_SIZE * sizeof(uint16_t)));
378                 
379                 // round up to next page boundary.
380                 virtio->queue.ring_used_addr = (virtio->queue.ring_used_addr + 0xfff) & ~0xfff;
381
382                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_desc_addr, (addr_t *)&(virtio->queue.desc)) == -1) {
383                     PrintError("Could not translate ring descriptor address\n");
384                     return -1;
385                 }
386
387
388                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_avail_addr, (addr_t *)&(virtio->queue.avail)) == -1) {
389                     PrintError("Could not translate ring available address\n");
390                     return -1;
391                 }
392
393
394                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_used_addr, (addr_t *)&(virtio->queue.used)) == -1) {
395                     PrintError("Could not translate ring used address\n");
396                     return -1;
397                 }
398
399                 PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
400                            (void *)(virtio->queue.ring_desc_addr),
401                            (void *)(virtio->queue.ring_avail_addr),
402                            (void *)(virtio->queue.ring_used_addr));
403
404                 PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
405                            virtio->queue.desc, virtio->queue.avail, virtio->queue.used);
406
407             } else {
408                 PrintError("Illegal write length for page frame number\n");
409                 return -1;
410             }
411             break;
412         case VRING_Q_SEL_PORT:
413             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
414
415             if (virtio->virtio_cfg.vring_queue_selector != 0) {
416                 PrintError("Virtio Block device only uses 1 queue, selected %d\n", 
417                            virtio->virtio_cfg.vring_queue_selector);
418                 return -1;
419             }
420
421             break;
422         case VRING_Q_NOTIFY_PORT:
423             PrintDebug("Handling Kick\n");
424             if (handle_kick(dev) == -1) {
425                 PrintError("Could not handle Block Notification\n");
426                 return -1;
427             }
428             break;
429         case VIRTIO_STATUS_PORT:
430             virtio->virtio_cfg.status = *(uint8_t *)src;
431
432             if (virtio->virtio_cfg.status == 0) {
433                 PrintDebug("Resetting device\n");
434                 virtio_reset(dev);
435             }
436
437             break;
438
439         case VIRTIO_ISR_PORT:
440             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
441             break;
442         default:
443             return -1;
444             break;
445     }
446
447     return length;
448 }
449
450
451 static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) {
452     struct vm_device * dev = (struct vm_device *)private_data;
453     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
454     int port_idx = port % virtio->io_range_size;
455
456
457     PrintDebug("VIRTIO BLOCK Read  for port %d (index =%d), length=%d\n", 
458                port, port_idx, length);
459
460     switch (port_idx) {
461         case HOST_FEATURES_PORT:
462             if (length != 4) {
463                 PrintError("Illegal read length for host features\n");
464                 return -1;
465             }
466
467             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
468         
469             break;
470         case VRING_PG_NUM_PORT:
471             if (length != 4) {
472                 PrintError("Illegal read length for page frame number\n");
473                 return -1;
474             }
475
476             *(uint32_t *)dst = virtio->queue.pfn;
477
478             break;
479         case VRING_SIZE_PORT:
480             if (length != 2) {
481                 PrintError("Illegal read length for vring size\n");
482                 return -1;
483             }
484                 
485             *(uint16_t *)dst = virtio->queue.queue_size;
486
487             break;
488
489         case VIRTIO_STATUS_PORT:
490             if (length != 1) {
491                 PrintError("Illegal read length for status\n");
492                 return -1;
493             }
494
495             *(uint8_t *)dst = virtio->virtio_cfg.status;
496             break;
497
498         case VIRTIO_ISR_PORT:
499             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
500             virtio->virtio_cfg.pci_isr = 0;
501             v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
502             break;
503
504         default:
505             if ( (port_idx >= sizeof(struct virtio_config)) && 
506                  (port_idx < (sizeof(struct virtio_config) + sizeof(struct blk_config))) ) {
507                 int cfg_offset = port_idx - sizeof(struct virtio_config);
508                 uint8_t * cfg_ptr = (uint8_t *)&(virtio->block_cfg);
509
510                 memcpy(dst, cfg_ptr + cfg_offset, length);
511                 
512             } else {
513                 PrintError("Read of Unhandled Virtio Read\n");
514                 return -1;
515             }
516           
517             break;
518     }
519
520     return length;
521 }
522
523
524
525
526 static struct v3_device_ops dev_ops = {
527     .free = virtio_free,
528     .reset = NULL,
529     .start = NULL,
530     .stop = NULL,
531 };
532
533
534
535
536 int v3_virtio_register_cdrom(struct vm_device * dev, struct v3_cd_ops * ops, void * private_data) {
537     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
538     
539     virtio->block_type = BLOCK_CDROM;
540     virtio->cd_ops = ops;
541     virtio->backend_data = private_data;
542
543     virtio->block_cfg.capacity = ops->get_capacity(private_data);
544
545     return 0;
546 }
547
548
549 int v3_virtio_register_harddisk(struct vm_device * dev, struct v3_hd_ops * ops, void * private_data) {
550     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
551
552     virtio->block_type = BLOCK_DISK;
553     virtio->hd_ops = ops;
554     virtio->backend_data = private_data;
555
556     virtio->block_cfg.capacity = ops->get_capacity(private_data);
557
558     PrintDebug("Virtio Capacity = %d -- 0x%p\n", (int)(virtio->block_cfg.capacity), 
559         (void *)(addr_t)(virtio->block_cfg.capacity));
560
561     return 0;
562 }
563
564
565
566 static int virtio_init(struct guest_info * vm, void * cfg_data) {
567     struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
568     struct virtio_blk_state * virtio_state = NULL;
569     struct pci_device * pci_dev = NULL;
570
571     PrintDebug("Initializing VIRTIO Block device\n");
572
573     if (pci_bus == NULL) {
574         PrintError("VirtIO devices require a PCI Bus");
575         return -1;
576     }
577
578     
579     virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
580     memset(virtio_state, 0, sizeof(struct virtio_blk_state));
581
582
583     struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &dev_ops, virtio_state);
584     if (v3_attach_device(vm, dev) == -1) {
585         PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
586         return -1;
587     }
588
589
590     // PCI initialization
591     {
592         struct v3_pci_bar bars[6];
593         int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
594         int tmp_ports = num_ports;
595         int i;
596
597
598
599         // This gets the number of ports, rounded up to a power of 2
600         virtio_state->io_range_size = 1; // must be a power of 2
601
602         while (tmp_ports > 0) {
603             tmp_ports >>= 1;
604             virtio_state->io_range_size <<= 1;
605         }
606         
607         // this is to account for any low order bits being set in num_ports
608         // if there are none, then num_ports was already a power of 2 so we shift right to reset it
609         if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
610             virtio_state->io_range_size >>= 1;
611         }
612
613
614         for (i = 0; i < 6; i++) {
615             bars[i].type = PCI_BAR_NONE;
616         }
617
618         PrintDebug("Virtio-BLK io_range_size = %d\n", virtio_state->io_range_size);
619
620         bars[0].type = PCI_BAR_IO;
621         bars[0].default_base_port = -1;
622         bars[0].num_ports = virtio_state->io_range_size;
623
624         bars[0].io_read = virtio_io_read;
625         bars[0].io_write = virtio_io_write;
626         bars[0].private_data = dev;
627
628         pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
629                                          0, PCI_AUTO_DEV_NUM, 0,
630                                          "LNX_VIRTIO_BLK", bars,
631                                          NULL, NULL, NULL, dev, NULL);
632
633         if (!pci_dev) {
634             PrintError("Could not register PCI Device\n");
635             return -1;
636         }
637         
638         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
639         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
640         
641
642         pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
643         pci_dev->config_header.class = PCI_CLASS_STORAGE;
644         pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
645     
646         pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
647
648
649         pci_dev->config_header.intr_pin = 1;
650
651         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
652
653
654         virtio_state->pci_dev = pci_dev;
655         virtio_state->pci_bus = pci_bus;
656     }
657
658     /* Block configuration */
659     virtio_state->virtio_cfg.host_features = VIRTIO_SEG_MAX;
660     virtio_state->block_cfg.max_seg = QUEUE_SIZE - 2;
661
662     // Virtio Block only uses one queue
663     virtio_state->queue.queue_size = QUEUE_SIZE;
664
665     virtio_reset(dev);
666
667
668
669     virtio_state->backend_data = NULL;
670     virtio_state->block_type = BLOCK_NONE;
671     virtio_state->hd_ops = NULL;
672
673     return 0;
674 }
675
676
677 device_register("LNX_VIRTIO_BLK", virtio_init)