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.


updates to virtio 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_pci.h>
23
24
25 #include <devices/pci.h>
26
27
28 struct blk_config {
29     uint64_t capacity;
30     uint32_t max_size;
31     uint32_t max_seg;
32     uint16_t cylinders;
33     uint8_t heads;
34     uint8_t sectors;
35 } __attribute__((packed));
36
37
38
39
40 /* Host Feature flags */
41 #define VIRTIO_BARRIER       0x01       /* Does host support barriers? */
42 #define VIRTIO_SIZE_MAX      0x02       /* Indicates maximum segment size */
43 #define VIRTIO_SEG_MAX       0x04       /* Indicates maximum # of segments */
44 #define VIRTIO_LEGACY_GEOM   0x10       /* Indicates support of legacy geometry */
45
46
47
48 struct virtio_blk_state {
49     struct blk_config block_cfg;
50     struct virtio_config virtio_cfg;
51
52     struct vm_device * pci_bus;
53     struct pci_device * pci_dev;
54
55     struct virtio_device * virtio_dev; // the virtio device struction for _this_ device
56     
57
58     int io_range_size;
59 };
60
61
62
63
64
65
66 static int virtio_free(struct vm_device * dev) {
67     return -1;
68 }
69
70
71
72
73 static struct v3_device_ops dev_ops = {
74     .free = virtio_free,
75     .reset = NULL,
76     .start = NULL,
77     .stop = NULL,
78 };
79
80
81
82
83
84
85 static int virtio_init(struct guest_info * vm, void * cfg_data) {
86     struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
87     struct virtio_blk_state * virtio_state = NULL;
88     struct pci_device * pci_dev = NULL;
89
90     PrintDebug("Initializing VIRTIO Block device\n");
91
92     if (pci_bus == NULL) {
93         PrintError("VirtIO devices require a PCI Bus");
94         return -1;
95     }
96
97     
98     virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
99     memset(virtio_state, 0, sizeof(struct virtio_blk_state));
100
101
102
103
104     struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &dev_ops, virtio_state);
105     if (v3_attach_device(vm, dev) == -1) {
106         PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
107         return -1;
108     }
109
110     struct v3_pci_bar bars[6];
111     int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
112     int tmp_ports = num_ports;
113     int i;
114
115
116
117     // This gets the number of ports, rounded up to a power of 2
118     virtio_state->io_range_size = 1; // must be a power of 2
119
120     while (tmp_ports > 0) {
121         tmp_ports >>= 1;
122         virtio_state->io_range_size <<= 1;
123     }
124         
125     // this is to account for any low order bits being set in num_ports
126     // if there are none, then num_ports was already a power of 2 so we shift right to reset it
127     if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
128         virtio_state->io_range_size >>= 1;
129     }
130
131
132     for (i = 0; i < 6; i++) {
133         bars[i].type = PCI_BAR_NONE;
134     }
135
136     bars[0].type = PCI_BAR_IO;
137     bars[0].default_base_port = -1;
138     bars[0].num_ports = virtio_state->io_range_size;
139
140     //    bars[0].io_read = virtio_io_read;
141     //  bars[0].io_write = virtio_io_write;
142
143     pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
144                                      0, PCI_AUTO_DEV_NUM, 0,
145                                      "LNX_VIRTIO_BLK", bars,
146                                      NULL, NULL, NULL, dev);
147
148     if (!pci_dev) {
149         PrintError("Could not register PCI Device\n");
150         return -1;
151     }
152         
153     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
154     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
155         
156
157     pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
158     pci_dev->config_header.class = PCI_CLASS_STORAGE;
159     pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
160     
161     pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
162
163
164     pci_dev->config_header.intr_pin = 1;
165
166     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
167
168
169     virtio_state->pci_dev = pci_dev;
170     virtio_state->pci_bus = pci_bus;
171
172     /* Block configuration */
173
174
175     
176     return -1;
177 }
178
179
180 device_register("LNX_VIRTIO_BLK", virtio_init)