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.


98c9a14edc075a9470f90ecdc7368e84f727c980
[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 blk_op_hdr * hdr, 
163                            struct vring_desc * buf_desc, uint8_t * status) {
164     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
165     uint8_t * buf = NULL;
166
167     PrintDebug("Handling Block op\n");
168
169
170
171     if (guest_pa_to_host_va(dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
172         PrintError("Could not translate buffer address\n");
173         return -1;
174     }
175
176
177     PrintDebug("Sector=%p Length=%d\n", (void *)(addr_t)(hdr->sector), buf_desc->length);
178
179     if (hdr->type == BLK_IN_REQ) {
180         if (virtio->block_type != BLOCK_NONE) {
181             if (handle_read_op(dev, buf, hdr->sector, buf_desc->length) == -1) {
182                 *status = BLK_STATUS_ERR;
183             } else {
184                 *status = BLK_STATUS_OK;
185             }
186         } else {
187             *status = BLK_STATUS_NOT_SUPPORTED;
188         }
189
190     } else if (hdr->type == BLK_OUT_REQ) {
191         if (virtio->block_type == BLOCK_DISK) {
192             if (handle_write_op(dev, buf, hdr->sector, buf_desc->length) == -1) {
193                 *status = BLK_STATUS_ERR;
194             } else {
195                 *status = BLK_STATUS_OK;
196             }
197         } else {
198             *status = BLK_STATUS_NOT_SUPPORTED;
199         }
200     } else if (hdr->type == BLK_SCSI_CMD) {
201         PrintDebug("VIRTIO: SCSI Command Not supported!!!\n");
202         *status = BLK_STATUS_NOT_SUPPORTED;
203     }
204
205     PrintDebug("Returning Status: %d\n", *status);
206
207     return 0;
208 }
209
210 static int get_desc_count(struct virtio_queue * q, int index) {
211     struct vring_desc * tmp_desc = &(q->desc[index]);
212     int cnt = 1;
213     
214     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
215         tmp_desc = &(q->desc[tmp_desc->next]);
216         cnt++;
217     }
218
219     return cnt;
220 }
221
222
223
224 static int handle_kick(struct vm_device * dev) {
225     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
226     struct virtio_queue * q = &(virtio->queue);
227
228     PrintDebug("VIRTIO KICK: cur_index=%d (mod=%d), avail_index=%d\n", 
229                q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
230
231     while (q->cur_avail_idx < q->avail->index) {
232         struct vring_desc * hdr_desc = NULL;
233         struct vring_desc * buf_desc = NULL;
234         struct vring_desc * status_desc = NULL;
235         struct blk_op_hdr * hdr = NULL;
236         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
237         int desc_cnt = get_desc_count(q, desc_idx);
238         int i = 0;
239         uint8_t * status_ptr = NULL;
240         uint8_t status = BLK_STATUS_OK;
241         uint32_t req_len = 0;
242
243         PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
244
245         if (desc_cnt < 3) {
246             PrintError("Block operations must include at least 3 descriptors\n");
247             return -1;
248         }
249
250         hdr_desc = &(q->desc[desc_idx]);
251
252
253         PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
254                    (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
255
256         if (guest_pa_to_host_va(dev->vm, hdr_desc->addr_gpa, (addr_t *)&(hdr)) == -1) {
257             PrintError("Could not translate block header address\n");
258             return -1;
259         }
260
261         desc_idx = hdr_desc->next;
262
263         for (i = 0; i < desc_cnt - 2; i++) {
264             uint8_t tmp_status = BLK_STATUS_OK;
265
266             buf_desc = &(q->desc[desc_idx]);
267
268             PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
269                        (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
270
271             if (handle_block_op(dev, hdr, buf_desc, &tmp_status) == -1) {
272                 PrintError("Error handling block operation\n");
273                 return -1;
274             }
275
276             if (tmp_status != BLK_STATUS_OK) {
277                 status = tmp_status;
278             }
279
280             req_len += buf_desc->length;
281             desc_idx = buf_desc->next;
282         }
283
284         status_desc = &(q->desc[desc_idx]);
285
286         PrintDebug("Status Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", status_desc, 
287                    (void *)(status_desc->addr_gpa), status_desc->length, status_desc->flags, status_desc->next);
288
289         if (guest_pa_to_host_va(dev->vm, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) {
290             PrintError("Could not translate status address\n");
291             return -1;
292         }
293
294         req_len += status_desc->length;
295         *status_ptr = status;
296
297         q->used->ring[q->used->index].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
298         q->used->ring[q->used->index].length = req_len; // What do we set this to????
299
300         q->used->index++;
301         q->cur_avail_idx++;
302     }
303
304     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
305         PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
306         v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
307         virtio->virtio_cfg.pci_isr = 1;
308     }
309
310     return 0;
311 }
312
313 static int virtio_io_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
314     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
315     int port_idx = port % virtio->io_range_size;
316
317
318     PrintDebug("VIRTIO BLOCK Write for port %d (index=%d) len=%d, value=%x\n", 
319                port, port_idx,  length, *(uint32_t *)src);
320
321
322
323     switch (port_idx) {
324         case GUEST_FEATURES_PORT:
325             if (length != 4) {
326                 PrintError("Illegal write length for guest features\n");
327                 return -1;
328             }
329             
330             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
331             PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
332
333             break;
334         case VRING_PG_NUM_PORT:
335             if (length == 4) {
336                 addr_t pfn = *(uint32_t *)src;
337                 addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
338
339
340                 virtio->queue.pfn = pfn;
341                 
342                 virtio->queue.ring_desc_addr = page_addr ;
343                 virtio->queue.ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
344                 virtio->queue.ring_used_addr = ( virtio->queue.ring_avail_addr + \
345                                                  sizeof(struct vring_avail)    + \
346                                                  (QUEUE_SIZE * sizeof(uint16_t)));
347                 
348                 // round up to next page boundary.
349                 virtio->queue.ring_used_addr = (virtio->queue.ring_used_addr + 0xfff) & ~0xfff;
350
351                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_desc_addr, (addr_t *)&(virtio->queue.desc)) == -1) {
352                     PrintError("Could not translate ring descriptor address\n");
353                     return -1;
354                 }
355
356
357                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_avail_addr, (addr_t *)&(virtio->queue.avail)) == -1) {
358                     PrintError("Could not translate ring available address\n");
359                     return -1;
360                 }
361
362
363                 if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_used_addr, (addr_t *)&(virtio->queue.used)) == -1) {
364                     PrintError("Could not translate ring used address\n");
365                     return -1;
366                 }
367
368                 PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
369                            (void *)(virtio->queue.ring_desc_addr),
370                            (void *)(virtio->queue.ring_avail_addr),
371                            (void *)(virtio->queue.ring_used_addr));
372
373                 PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
374                            virtio->queue.desc, virtio->queue.avail, virtio->queue.used);
375
376             } else {
377                 PrintError("Illegal write length for page frame number\n");
378                 return -1;
379             }
380             break;
381         case VRING_Q_SEL_PORT:
382             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
383
384             if (virtio->virtio_cfg.vring_queue_selector != 0) {
385                 PrintError("Virtio Block device only uses 1 queue, selected %d\n", 
386                            virtio->virtio_cfg.vring_queue_selector);
387                 return -1;
388             }
389
390             break;
391         case VRING_Q_NOTIFY_PORT:
392             PrintDebug("Handling Kick\n");
393             if (handle_kick(dev) == -1) {
394                 PrintError("Could not handle Block Notification\n");
395                 return -1;
396             }
397             break;
398         case VIRTIO_STATUS_PORT:
399             virtio->virtio_cfg.status = *(uint8_t *)src;
400
401             if (virtio->virtio_cfg.status == 0) {
402                 PrintDebug("Resetting device\n");
403                 virtio_reset(dev);
404             }
405
406             break;
407
408         case VIRTIO_ISR_PORT:
409             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
410             break;
411         default:
412             return -1;
413             break;
414     }
415
416     return length;
417 }
418
419
420 static int virtio_io_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
421     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
422     int port_idx = port % virtio->io_range_size;
423
424
425     PrintDebug("VIRTIO BLOCK Read  for port %d (index =%d), length=%d\n", 
426                port, port_idx, length);
427
428     switch (port_idx) {
429         case HOST_FEATURES_PORT:
430             if (length != 4) {
431                 PrintError("Illegal read length for host features\n");
432                 return -1;
433             }
434
435             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
436         
437             break;
438         case VRING_PG_NUM_PORT:
439             if (length != 4) {
440                 PrintError("Illegal read length for page frame number\n");
441                 return -1;
442             }
443
444             *(uint32_t *)dst = virtio->queue.pfn;
445
446             break;
447         case VRING_SIZE_PORT:
448             if (length != 2) {
449                 PrintError("Illegal read length for vring size\n");
450                 return -1;
451             }
452                 
453             *(uint16_t *)dst = virtio->queue.queue_size;
454
455             break;
456
457         case VIRTIO_STATUS_PORT:
458             if (length != 1) {
459                 PrintError("Illegal read length for status\n");
460                 return -1;
461             }
462
463             *(uint8_t *)dst = virtio->virtio_cfg.status;
464             break;
465
466         case VIRTIO_ISR_PORT:
467             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
468             virtio->virtio_cfg.pci_isr = 0;
469             v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
470             break;
471
472         default:
473             if ( (port_idx >= sizeof(struct virtio_config)) && 
474                  (port_idx < (sizeof(struct virtio_config) + sizeof(struct blk_config))) ) {
475                 int cfg_offset = port_idx - sizeof(struct virtio_config);
476                 uint8_t * cfg_ptr = (uint8_t *)&(virtio->block_cfg);
477
478                 memcpy(dst, cfg_ptr + cfg_offset, length);
479                 
480             } else {
481                 PrintError("Read of Unhandled Virtio Read\n");
482                 return -1;
483             }
484           
485             break;
486     }
487
488     return length;
489 }
490
491
492
493
494 static struct v3_device_ops dev_ops = {
495     .free = virtio_free,
496     .reset = NULL,
497     .start = NULL,
498     .stop = NULL,
499 };
500
501
502
503
504 int v3_virtio_register_cdrom(struct vm_device * dev, struct v3_cd_ops * ops, void * private_data) {
505     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
506     
507     virtio->block_type = BLOCK_CDROM;
508     virtio->cd_ops = ops;
509     virtio->backend_data = private_data;
510
511     virtio->block_cfg.capacity = ops->get_capacity(private_data);
512
513     return 0;
514 }
515
516
517 int v3_virtio_register_harddisk(struct vm_device * dev, struct v3_hd_ops * ops, void * private_data) {
518     struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
519
520     virtio->block_type = BLOCK_DISK;
521     virtio->hd_ops = ops;
522     virtio->backend_data = private_data;
523
524     virtio->block_cfg.capacity = ops->get_capacity(private_data);
525
526     PrintDebug("Virtio Capacity = %d -- 0x%p\n", (int)(virtio->block_cfg.capacity), 
527         (void *)(addr_t)(virtio->block_cfg.capacity));
528
529     return 0;
530 }
531
532
533
534 static int virtio_init(struct guest_info * vm, void * cfg_data) {
535     struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
536     struct virtio_blk_state * virtio_state = NULL;
537     struct pci_device * pci_dev = NULL;
538
539     PrintDebug("Initializing VIRTIO Block device\n");
540
541     if (pci_bus == NULL) {
542         PrintError("VirtIO devices require a PCI Bus");
543         return -1;
544     }
545
546     
547     virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
548     memset(virtio_state, 0, sizeof(struct virtio_blk_state));
549
550
551     struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &dev_ops, virtio_state);
552     if (v3_attach_device(vm, dev) == -1) {
553         PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
554         return -1;
555     }
556
557
558     // PCI initialization
559     {
560         struct v3_pci_bar bars[6];
561         int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
562         int tmp_ports = num_ports;
563         int i;
564
565
566
567         // This gets the number of ports, rounded up to a power of 2
568         virtio_state->io_range_size = 1; // must be a power of 2
569
570         while (tmp_ports > 0) {
571             tmp_ports >>= 1;
572             virtio_state->io_range_size <<= 1;
573         }
574         
575         // this is to account for any low order bits being set in num_ports
576         // if there are none, then num_ports was already a power of 2 so we shift right to reset it
577         if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
578             virtio_state->io_range_size >>= 1;
579         }
580
581
582         for (i = 0; i < 6; i++) {
583             bars[i].type = PCI_BAR_NONE;
584         }
585
586         bars[0].type = PCI_BAR_IO;
587         bars[0].default_base_port = -1;
588         bars[0].num_ports = virtio_state->io_range_size;
589
590         bars[0].io_read = virtio_io_read;
591         bars[0].io_write = virtio_io_write;
592
593         pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
594                                          0, PCI_AUTO_DEV_NUM, 0,
595                                          "LNX_VIRTIO_BLK", bars,
596                                          NULL, NULL, NULL, dev);
597
598         if (!pci_dev) {
599             PrintError("Could not register PCI Device\n");
600             return -1;
601         }
602         
603         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
604         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
605         
606
607         pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
608         pci_dev->config_header.class = PCI_CLASS_STORAGE;
609         pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
610     
611         pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
612
613
614         pci_dev->config_header.intr_pin = 1;
615
616         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
617
618
619         virtio_state->pci_dev = pci_dev;
620         virtio_state->pci_bus = pci_bus;
621     }
622
623     /* Block configuration */
624     virtio_state->virtio_cfg.host_features = VIRTIO_SEG_MAX;
625     virtio_state->block_cfg.max_seg = QUEUE_SIZE - 2;
626
627     // Virtio Block only uses one queue
628     virtio_state->queue.queue_size = QUEUE_SIZE;
629
630     virtio_reset(dev);
631
632
633
634     virtio_state->backend_data = NULL;
635     virtio_state->block_type = BLOCK_NONE;
636     virtio_state->hd_ops = NULL;
637
638     return 0;
639 }
640
641
642 device_register("LNX_VIRTIO_BLK", virtio_init)