1 | /* |
2 | * VirtioBus |
3 | * |
4 | * Copyright (C) 2012 : GreenSocs Ltd |
5 | * http://www.greensocs.com/ , email: info@greensocs.com |
6 | * |
7 | * Developed by : |
8 | * Frederic Konrad <fred.konrad@greensocs.com> |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation, either version 2 of the License, or |
13 | * (at your option) any later version. |
14 | * |
15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU General Public License along |
21 | * with this program; if not, see <http://www.gnu.org/licenses/>. |
22 | * |
23 | */ |
24 | |
25 | #ifndef VIRTIO_BUS_H |
26 | #define VIRTIO_BUS_H |
27 | |
28 | #include "hw/qdev-core.h" |
29 | #include "hw/virtio/virtio.h" |
30 | |
31 | #define TYPE_VIRTIO_BUS "virtio-bus" |
32 | #define VIRTIO_BUS_GET_CLASS(obj) \ |
33 | OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS) |
34 | #define VIRTIO_BUS_CLASS(klass) \ |
35 | OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS) |
36 | #define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS) |
37 | |
38 | typedef struct VirtioBusState VirtioBusState; |
39 | |
40 | typedef struct VirtioBusClass { |
41 | /* This is what a VirtioBus must implement */ |
42 | BusClass parent; |
43 | void (*notify)(DeviceState *d, uint16_t vector); |
44 | void (*save_config)(DeviceState *d, QEMUFile *f); |
45 | void (*save_queue)(DeviceState *d, int n, QEMUFile *f); |
46 | void (*)(DeviceState *d, QEMUFile *f); |
47 | int (*load_config)(DeviceState *d, QEMUFile *f); |
48 | int (*load_queue)(DeviceState *d, int n, QEMUFile *f); |
49 | int (*load_done)(DeviceState *d, QEMUFile *f); |
50 | int (*)(DeviceState *d, QEMUFile *f); |
51 | bool (*)(DeviceState *d); |
52 | bool (*query_guest_notifiers)(DeviceState *d); |
53 | int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); |
54 | int (*set_host_notifier_mr)(DeviceState *d, int n, |
55 | MemoryRegion *mr, bool assign); |
56 | void (*vmstate_change)(DeviceState *d, bool running); |
57 | /* |
58 | * Expose the features the transport layer supports before |
59 | * the negotiation takes place. |
60 | */ |
61 | void (*pre_plugged)(DeviceState *d, Error **errp); |
62 | /* |
63 | * transport independent init function. |
64 | * This is called by virtio-bus just after the device is plugged. |
65 | */ |
66 | void (*device_plugged)(DeviceState *d, Error **errp); |
67 | /* |
68 | * transport independent exit function. |
69 | * This is called by virtio-bus just before the device is unplugged. |
70 | */ |
71 | void (*device_unplugged)(DeviceState *d); |
72 | int (*query_nvectors)(DeviceState *d); |
73 | /* |
74 | * ioeventfd handling: if the transport implements ioeventfd_assign, |
75 | * it must implement ioeventfd_enabled as well. |
76 | */ |
77 | /* Returns true if the ioeventfd is enabled for the device. */ |
78 | bool (*ioeventfd_enabled)(DeviceState *d); |
79 | /* |
80 | * Assigns/deassigns the ioeventfd backing for the transport on |
81 | * the device for queue number n. Returns an error value on |
82 | * failure. |
83 | */ |
84 | int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier, |
85 | int n, bool assign); |
86 | /* |
87 | * Does the transport have variable vring alignment? |
88 | * (ie can it ever call virtio_queue_set_align()?) |
89 | * Note that changing this will break migration for this transport. |
90 | */ |
91 | bool has_variable_vring_alignment; |
92 | AddressSpace *(*get_dma_as)(DeviceState *d); |
93 | } VirtioBusClass; |
94 | |
95 | struct VirtioBusState { |
96 | BusState parent_obj; |
97 | |
98 | /* |
99 | * Set if ioeventfd has been started. |
100 | */ |
101 | bool ioeventfd_started; |
102 | |
103 | /* |
104 | * Set if ioeventfd has been grabbed by vhost. When ioeventfd |
105 | * is grabbed by vhost, we track its started/stopped state (which |
106 | * depends in turn on the virtio status register), but do not |
107 | * register a handler for the ioeventfd. When ioeventfd is |
108 | * released, if ioeventfd_started is true we finally register |
109 | * the handler so that QEMU's device model can use ioeventfd. |
110 | */ |
111 | int ioeventfd_grabbed; |
112 | }; |
113 | |
114 | void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp); |
115 | void virtio_bus_reset(VirtioBusState *bus); |
116 | void virtio_bus_device_unplugged(VirtIODevice *bus); |
117 | /* Get the device id of the plugged device. */ |
118 | uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus); |
119 | /* Get the config_len field of the plugged device. */ |
120 | size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); |
121 | /* Get bad features of the plugged device. */ |
122 | uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); |
123 | /* Get config of the plugged device. */ |
124 | void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config); |
125 | /* Set config of the plugged device. */ |
126 | void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config); |
127 | |
128 | static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus) |
129 | { |
130 | BusState *qbus = &bus->parent_obj; |
131 | BusChild *kid = QTAILQ_FIRST(&qbus->children); |
132 | DeviceState *qdev = kid ? kid->child : NULL; |
133 | |
134 | /* This is used on the data path, the cast is guaranteed |
135 | * to succeed by the qdev machinery. |
136 | */ |
137 | return (VirtIODevice *)qdev; |
138 | } |
139 | |
140 | /* Return whether the proxy allows ioeventfd. */ |
141 | bool virtio_bus_ioeventfd_enabled(VirtioBusState *bus); |
142 | /* Start the ioeventfd. */ |
143 | int virtio_bus_start_ioeventfd(VirtioBusState *bus); |
144 | /* Stop the ioeventfd. */ |
145 | void virtio_bus_stop_ioeventfd(VirtioBusState *bus); |
146 | /* Tell the bus that vhost is grabbing the ioeventfd. */ |
147 | int virtio_bus_grab_ioeventfd(VirtioBusState *bus); |
148 | /* bus that vhost is not using the ioeventfd anymore. */ |
149 | void virtio_bus_release_ioeventfd(VirtioBusState *bus); |
150 | /* Switch from/to the generic ioeventfd handler */ |
151 | int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign); |
152 | /* Tell the bus that the ioeventfd handler is no longer required. */ |
153 | void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n); |
154 | |
155 | #endif /* VIRTIO_BUS_H */ |
156 | |