xref: /openbsd-src/sys/dev/pci/virtio_pci.c (revision 9b9d2a55a62c8e82206c25f94fcc7f4e2765250e)
1 /*	$OpenBSD: virtio_pci.c,v 1.11 2015/07/18 16:35:33 sf Exp $	*/
2 /*	$NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $	*/
3 
4 /*
5  * Copyright (c) 2012 Stefan Fritsch.
6  * Copyright (c) 2010 Minoura Makoto.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/device.h>
33 #include <sys/mutex.h>
34 
35 #include <dev/pci/pcidevs.h>
36 #include <dev/pci/pcireg.h>
37 #include <dev/pci/pcivar.h>
38 
39 #include <dev/pci/virtioreg.h>
40 #include <dev/pci/virtiovar.h>
41 
42 /*
43  * XXX: Before being used on big endian arches, the access to config registers
44  * XXX: needs to be reviewed/fixed. The non-device specific registers are
45  * XXX: PCI-endian while the device specific registers are native endian.
46  */
47 
48 #define virtio_set_status(sc, s) virtio_pci_set_status(sc, s)
49 #define virtio_device_reset(sc) virtio_set_status((sc), 0)
50 
51 int		virtio_pci_match(struct device *, void *, void *);
52 void		virtio_pci_attach(struct device *, struct device *, void *);
53 int		virtio_pci_detach(struct device *, int);
54 
55 void		virtio_pci_kick(struct virtio_softc *, uint16_t);
56 uint8_t		virtio_pci_read_device_config_1(struct virtio_softc *, int);
57 uint16_t	virtio_pci_read_device_config_2(struct virtio_softc *, int);
58 uint32_t	virtio_pci_read_device_config_4(struct virtio_softc *, int);
59 uint64_t	virtio_pci_read_device_config_8(struct virtio_softc *, int);
60 void		virtio_pci_write_device_config_1(struct virtio_softc *, int, uint8_t);
61 void		virtio_pci_write_device_config_2(struct virtio_softc *, int, uint16_t);
62 void		virtio_pci_write_device_config_4(struct virtio_softc *, int, uint32_t);
63 void		virtio_pci_write_device_config_8(struct virtio_softc *, int, uint64_t);
64 uint16_t	virtio_pci_read_queue_size(struct virtio_softc *, uint16_t);
65 void		virtio_pci_setup_queue(struct virtio_softc *, uint16_t, uint32_t);
66 void		virtio_pci_set_status(struct virtio_softc *, int);
67 uint32_t	virtio_pci_negotiate_features(struct virtio_softc *, uint32_t,
68 					      const struct virtio_feature_name *);
69 int		virtio_pci_intr(void *);
70 
71 struct virtio_pci_softc {
72 	struct virtio_softc	sc_sc;
73 	pci_chipset_tag_t	sc_pc;
74 
75 	bus_space_tag_t		sc_iot;
76 	bus_space_handle_t	sc_ioh;
77 	bus_size_t		sc_iosize;
78 
79 	void                    *sc_ih;
80 
81 	int			sc_config_offset;
82 };
83 
84 struct cfattach virtio_pci_ca = {
85 	sizeof(struct virtio_pci_softc),
86 	virtio_pci_match,
87 	virtio_pci_attach,
88 	virtio_pci_detach,
89 	NULL
90 };
91 
92 struct virtio_ops virtio_pci_ops = {
93 	virtio_pci_kick,
94 	virtio_pci_read_device_config_1,
95 	virtio_pci_read_device_config_2,
96 	virtio_pci_read_device_config_4,
97 	virtio_pci_read_device_config_8,
98 	virtio_pci_write_device_config_1,
99 	virtio_pci_write_device_config_2,
100 	virtio_pci_write_device_config_4,
101 	virtio_pci_write_device_config_8,
102 	virtio_pci_read_queue_size,
103 	virtio_pci_setup_queue,
104 	virtio_pci_set_status,
105 	virtio_pci_negotiate_features,
106 	virtio_pci_intr,
107 };
108 
109 uint16_t
110 virtio_pci_read_queue_size(struct virtio_softc *vsc, uint16_t idx)
111 {
112 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
113 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT,
114 	    idx);
115 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh,
116 	    VIRTIO_CONFIG_QUEUE_SIZE);
117 }
118 
119 void
120 virtio_pci_setup_queue(struct virtio_softc *vsc, uint16_t idx, uint32_t addr)
121 {
122 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
123 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT,
124 	    idx);
125 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS,
126 	    addr);
127 }
128 
129 void
130 virtio_pci_set_status(struct virtio_softc *vsc, int status)
131 {
132 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
133 	int old = 0;
134 
135 	if (status != 0)
136 		old = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
137 				       VIRTIO_CONFIG_DEVICE_STATUS);
138 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_STATUS,
139 			  status|old);
140 }
141 
142 int
143 virtio_pci_match(struct device *parent, void *match, void *aux)
144 {
145 	struct pci_attach_args *pa;
146 
147 	pa = (struct pci_attach_args *)aux;
148 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_QUMRANET &&
149 	    PCI_PRODUCT(pa->pa_id) >= 0x1000 &&
150 	    PCI_PRODUCT(pa->pa_id) <= 0x103f &&
151 	    PCI_REVISION(pa->pa_class) == 0)
152 		return 1;
153 	return 0;
154 }
155 
156 void
157 virtio_pci_attach(struct device *parent, struct device *self, void *aux)
158 {
159 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self;
160 	struct virtio_softc *vsc = &sc->sc_sc;
161 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
162 	pci_chipset_tag_t pc = pa->pa_pc;
163 	pcitag_t tag = pa->pa_tag;
164 	int revision;
165 	pcireg_t id;
166 	char const *intrstr;
167 	pci_intr_handle_t ih;
168 
169 	revision = PCI_REVISION(pa->pa_class);
170 	if (revision != 0) {
171 		printf("unknown revision 0x%02x; giving up\n", revision);
172 		return;
173 	}
174 
175 	/* subsystem ID shows what I am */
176 	id = PCI_PRODUCT(pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG));
177 	printf(": Virtio %s Device", virtio_device_string(id));
178 
179 #ifdef notyet
180 	if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, NULL))
181 		printf(", msix capable");
182 #endif
183 	printf("\n");
184 
185 	vsc->sc_ops = &virtio_pci_ops;
186 	sc->sc_pc = pc;
187 	vsc->sc_dmat = pa->pa_dmat;
188 	sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
189 
190 	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
191 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize, 0)) {
192 		printf("%s: can't map i/o space\n", vsc->sc_dev.dv_xname);
193 		return;
194 	}
195 
196 	virtio_device_reset(vsc);
197 	virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
198 	virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
199 
200 	/* XXX: use softc as aux... */
201 	vsc->sc_childdevid = id;
202 	vsc->sc_child = NULL;
203 	config_found(self, sc, NULL);
204 	if (vsc->sc_child == NULL) {
205 		printf("%s: no matching child driver; not configured\n",
206 		    vsc->sc_dev.dv_xname);
207 		goto fail_1;
208 	}
209 	if (vsc->sc_child == VIRTIO_CHILD_ERROR) {
210 		printf("%s: virtio configuration failed\n",
211 		    vsc->sc_dev.dv_xname);
212 		goto fail_1;
213 	}
214 
215 	if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
216 		printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname);
217 		goto fail_2;
218 	}
219 	intrstr = pci_intr_string(pc, ih);
220 	/*
221 	 * We always set the IPL_MPSAFE flag in order to do the relatively
222 	 * expensive ISR read without lock, and then grab the kernel lock in
223 	 * the interrupt handler.
224 	 * For now, we don't support IPL_MPSAFE vq_done functions.
225 	 */
226 	KASSERT((vsc->sc_ipl & IPL_MPSAFE) == 0);
227 	sc->sc_ih = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE,
228 	    virtio_pci_intr, sc, vsc->sc_dev.dv_xname);
229 	if (sc->sc_ih == NULL) {
230 		printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname);
231 		if (intrstr != NULL)
232 			printf(" at %s", intrstr);
233 		printf("\n");
234 		goto fail_2;
235 	}
236 	printf("%s: %s\n", vsc->sc_dev.dv_xname, intrstr);
237 
238 	virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
239 	return;
240 
241 fail_2:
242 	config_detach(vsc->sc_child, 0);
243 fail_1:
244 	/* no pci_mapreg_unmap() or pci_intr_unmap() */
245 	virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
246 }
247 
248 int
249 virtio_pci_detach(struct device *self, int flags)
250 {
251 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self;
252 	struct virtio_softc *vsc = &sc->sc_sc;
253 	int r;
254 
255 	if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) {
256 		r = config_detach(vsc->sc_child, flags);
257 		if (r)
258 			return r;
259 	}
260 	KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR);
261 	KASSERT(vsc->sc_vqs == 0);
262 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
263 	sc->sc_ih = 0;
264 	if (sc->sc_iosize)
265 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize);
266 	sc->sc_iosize = 0;
267 
268 	return 0;
269 }
270 
271 /*
272  * Feature negotiation.
273  * Prints available / negotiated features if guest_feature_names != NULL and
274  * VIRTIO_DEBUG is 1
275  */
276 uint32_t
277 virtio_pci_negotiate_features(struct virtio_softc *vsc, uint32_t guest_features,
278     const struct virtio_feature_name *guest_feature_names)
279 {
280 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
281 	uint32_t host, neg;
282 
283 	/*
284 	 * indirect descriptors can be switched off by setting bit 1 in the
285 	 * driver flags, see config(8)
286 	 */
287 	if (!(vsc->sc_dev.dv_cfdata->cf_flags & 1) &&
288 	    !(vsc->sc_child->dv_cfdata->cf_flags & 1)) {
289 		guest_features |= VIRTIO_F_RING_INDIRECT_DESC;
290 	} else {
291 		printf("RingIndirectDesc disabled by UKC\n");
292 	}
293 	host = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
294 				VIRTIO_CONFIG_DEVICE_FEATURES);
295 	neg = host & guest_features;
296 #if VIRTIO_DEBUG
297 	if (guest_feature_names)
298 		virtio_log_features(host, neg, guest_feature_names);
299 #endif
300 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
301 			  VIRTIO_CONFIG_GUEST_FEATURES, neg);
302 	vsc->sc_features = neg;
303 	if (neg & VIRTIO_F_RING_INDIRECT_DESC)
304 		vsc->sc_indirect = 1;
305 	else
306 		vsc->sc_indirect = 0;
307 
308 	return neg;
309 }
310 
311 /*
312  * Device configuration registers.
313  */
314 uint8_t
315 virtio_pci_read_device_config_1(struct virtio_softc *vsc, int index)
316 {
317 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
318 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh,
319 	    sc->sc_config_offset + index);
320 }
321 
322 uint16_t
323 virtio_pci_read_device_config_2(struct virtio_softc *vsc, int index)
324 {
325 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
326 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh,
327 	    sc->sc_config_offset + index);
328 }
329 
330 uint32_t
331 virtio_pci_read_device_config_4(struct virtio_softc *vsc, int index)
332 {
333 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
334 	return bus_space_read_4(sc->sc_iot, sc->sc_ioh,
335 	    sc->sc_config_offset + index);
336 }
337 
338 uint64_t
339 virtio_pci_read_device_config_8(struct virtio_softc *vsc, int index)
340 {
341 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
342 	uint64_t r;
343 
344 	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
345 	    sc->sc_config_offset + index + sizeof(uint32_t));
346 	r <<= 32;
347 	r += bus_space_read_4(sc->sc_iot, sc->sc_ioh,
348 	    sc->sc_config_offset + index);
349 	return r;
350 }
351 
352 void
353 virtio_pci_write_device_config_1(struct virtio_softc *vsc, int index,
354     uint8_t value)
355 {
356 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
357 	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
358 	    sc->sc_config_offset + index, value);
359 }
360 
361 void
362 virtio_pci_write_device_config_2(struct virtio_softc *vsc, int index,
363     uint16_t value)
364 {
365 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
366 	bus_space_write_2(sc->sc_iot, sc->sc_ioh,
367 	    sc->sc_config_offset + index, value);
368 }
369 
370 void
371 virtio_pci_write_device_config_4(struct virtio_softc *vsc,
372 			     int index, uint32_t value)
373 {
374 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
375 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
376 	    sc->sc_config_offset + index, value);
377 }
378 
379 void
380 virtio_pci_write_device_config_8(struct virtio_softc *vsc,
381 			     int index, uint64_t value)
382 {
383 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
384 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
385 	    sc->sc_config_offset + index, value & 0xffffffff);
386 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
387 	    sc->sc_config_offset + index + sizeof(uint32_t), value >> 32);
388 }
389 
390 /*
391  * Interrupt handler.
392  */
393 int
394 virtio_pci_intr(void *arg)
395 {
396 	struct virtio_pci_softc *sc = arg;
397 	struct virtio_softc *vsc = &sc->sc_sc;
398 	int isr, r = 0;
399 
400 	/* check and ack the interrupt */
401 	isr = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
402 	    VIRTIO_CONFIG_ISR_STATUS);
403 	if (isr == 0)
404 		return 0;
405 	KERNEL_LOCK();
406 	if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) &&
407 	    (vsc->sc_config_change != NULL))
408 		r = (vsc->sc_config_change)(vsc);
409 	if (vsc->sc_intrhand != NULL)
410 		r |= (vsc->sc_intrhand)(vsc);
411 	KERNEL_UNLOCK();
412 
413 	return r;
414 }
415 
416 void
417 virtio_pci_kick(struct virtio_softc *vsc, uint16_t idx)
418 {
419 	struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
420 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_NOTIFY,
421 	    idx);
422 }
423