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.


added initial VirtIO and symbiotic swap devices
[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 static int virtio_init(struct vm_device * dev) {
55     struct blk_state * virtio = (struct blk_state *)(dev->private_data);
56
57     PrintDebug("Initializing VIRTIO Block device\n");
58
59     if (virtio->pci_bus != NULL) {
60         struct v3_pci_bar bars[6];
61         struct pci_device * pci_dev = NULL;
62         int i;
63         int num_ports_pow2 = 1;
64         int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
65         
66
67         // This gets the number of ports, rounded up to a power of 2
68         while (num_ports > 0) {
69             num_ports >>= 1;
70             num_ports_pow2 <<= 1;
71         }
72         
73         // reset num_ports 
74         num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
75
76         if (num_ports  & ((num_ports_pow2 >> 1) - 1)) {
77             num_ports_pow2 >>= 1;
78         }
79
80
81         for (i = 0; i < 6; i++) {
82             bars[i].type = PCI_BAR_NONE;
83         }
84
85         bars[0].type = PCI_BAR_IO;
86         bars[0].default_base_port = -1;
87         bars[0].num_ports = num_ports_pow2;
88
89         bars[0].io_read = virtio_pci_read;
90         bars[0].io_write = virtio_pci_write;
91
92         pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
93                                          0, PCI_AUTO_DEV_NUM, 0,
94                                          "VIRTIO-BLK", bars,
95                                          NULL, NULL, NULL, dev);
96
97         if (!pci_dev) {
98             PrintError("Could not register PCI Device\n");
99             return -1;
100         }
101         
102         pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
103         pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
104         pci_dev->config_header.class = PCI_CLASS_STORAGE;
105         pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
106
107         pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
108         pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
109
110         pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
111     }
112
113
114
115     return -1;
116 }
117
118 static int virtio_deinit(struct vm_device * dev) {
119     return -1;
120 }
121
122
123
124 static struct vm_device_ops dev_ops = {
125     .init = virtio_init, 
126     .deinit = virtio_deinit,
127     .reset = NULL,
128     .start = NULL,
129     .stop = NULL,
130 };
131
132
133
134 struct vm_device * v3_create_virtio(struct vm_device * pci_bus) {
135     struct blk_state * virtio = NULL;
136
137     PrintDebug("Creating VirtIO Block device\n");
138
139     if (pci_bus == NULL) {
140         PrintError("VirtIO requires a PCI bus\n");
141         return NULL;
142     }
143
144
145     virtio = (struct blk_state *)V3_Malloc(sizeof(struct blk_state));
146
147     virtio->pci_bus = pci_bus;
148
149     return v3_create_device("VIRTIO_BLK", &dev_ops, virtio);
150 }