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.


Update to the device framework.
[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
22 #include <devices/lnx_virtio.h>
23 #include <devices/pci.h>
24
25
26
27 struct blk_config {
28     uint64_t capacity;
29     uint32_t max_size;
30     uint32_t max_seg;
31     uint16_t cylinders;
32     uint8_t heads;
33     uint8_t sectors;
34 } __attribute__((packed));
35
36 struct blk_state {
37
38     struct blk_config cfg;
39
40     struct vm_device * pci_bus;
41 };
42
43
44
45 static int virtio_pci_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
46     return -1;
47 }
48
49
50 static int virtio_pci_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
51     return -1;
52 }
53
54
55
56 static int virtio_free(struct vm_device * dev) {
57     return -1;
58 }
59
60
61
62 static struct v3_device_ops dev_ops = {
63     .free = virtio_free,
64     .reset = NULL,
65     .start = NULL,
66     .stop = NULL,
67 };
68
69
70
71
72
73 static int virtio_init(struct guest_info * vm, void * cfg_data) {
74     struct blk_state * virtio = NULL;
75     struct vm_device * pci_bus = (struct vm_device *)cfg_data;
76
77
78     PrintDebug("Initializing VIRTIO Block device\n");
79
80     if (pci_bus == NULL) {
81         PrintError("VirtIO requires a PCI bus\n");
82         return -1;
83     }
84
85     virtio = (struct blk_state *)V3_Malloc(sizeof(struct blk_state));
86
87     virtio->pci_bus = pci_bus;
88
89     struct vm_device * dev = v3_allocate_device("VIRTIO_BLK", &dev_ops, virtio);
90     if (v3_attach_device(vm, dev) == -1) {
91         PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
92         return -1;
93     }
94
95
96
97     if (virtio->pci_bus != NULL) {
98         struct v3_pci_bar bars[6];
99         struct pci_device * pci_dev = NULL;
100         int i;
101         int num_ports_pow2 = 1;
102         int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
103         
104
105         // This gets the number of ports, rounded up to a power of 2
106         while (num_ports > 0) {
107             num_ports >>= 1;
108             num_ports_pow2 <<= 1;
109         }
110         
111         // reset num_ports 
112         num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
113
114         if (num_ports  & ((num_ports_pow2 >> 1) - 1)) {
115             num_ports_pow2 >>= 1;
116         }
117
118
119         for (i = 0; i < 6; i++) {
120             bars[i].type = PCI_BAR_NONE;
121         }
122
123         bars[0].type = PCI_BAR_IO;
124         bars[0].default_base_port = -1;
125         bars[0].num_ports = num_ports_pow2;
126
127         bars[0].io_read = virtio_pci_read;
128         bars[0].io_write = virtio_pci_write;
129
130         pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
131                                          0, PCI_AUTO_DEV_NUM, 0,
132                                          "VIRTIO-BLK", bars,
133                                          NULL, NULL, NULL, dev);
134
135         if (!pci_dev) {
136             PrintError("Could not register PCI Device\n");
137             return -1;
138         }
139         
140         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
141         pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
142         pci_dev->config_header.class = PCI_CLASS_STORAGE;
143         pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
144
145         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
146         pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
147
148         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
149     }
150
151
152
153     return -1;
154 }
155
156
157 device_register("LNX_VIRTIO_BLK", virtio_init)