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.


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