Thu Jan 28 15:43:13 2021 UTC ()
Rewrite and streamline virtio device config read/write and explicitly cater
for the Aarch64-eb bus problem with Qemu. This removes lots of bus_space
`magic' and cleans up the code.


(reinoud)
diff -r1.44 -r1.45 src/sys/dev/pci/virtio.c
diff -r1.26 -r1.27 src/sys/dev/pci/virtio_pci.c
diff -r1.18 -r1.19 src/sys/dev/pci/virtiovar.h
diff -r1.4 -r1.5 src/sys/dev/virtio/virtio_mmio.c

cvs diff -r1.44 -r1.45 src/sys/dev/pci/virtio.c (expand / switch to unified diff)

--- src/sys/dev/pci/virtio.c 2021/01/20 21:59:48 1.44
+++ src/sys/dev/pci/virtio.c 2021/01/28 15:43:12 1.45
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: virtio.c,v 1.44 2021/01/20 21:59:48 reinoud Exp $ */ 1/* $NetBSD: virtio.c,v 1.45 2021/01/28 15:43:12 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. 5 * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg.
6 * Copyright (c) 2010 Minoura Makoto. 6 * Copyright (c) 2010 Minoura Makoto.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -18,27 +18,27 @@ @@ -18,27 +18,27 @@
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 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 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 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 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 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. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.44 2021/01/20 21:59:48 reinoud Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.45 2021/01/28 15:43:12 reinoud Exp $");
32 32
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/kernel.h> 35#include <sys/kernel.h>
36#include <sys/atomic.h> 36#include <sys/atomic.h>
37#include <sys/bus.h> 37#include <sys/bus.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/kmem.h> 39#include <sys/kmem.h>
40#include <sys/module.h> 40#include <sys/module.h>
41 41
42#define VIRTIO_PRIVATE 42#define VIRTIO_PRIVATE
43 43
44#include <dev/pci/virtioreg.h> /* XXX: move to non-pci */ 44#include <dev/pci/virtioreg.h> /* XXX: move to non-pci */
@@ -136,155 +136,265 @@ virtio_negotiate_features(struct virtio_ @@ -136,155 +136,265 @@ virtio_negotiate_features(struct virtio_
136 sc->sc_indirect = false; 136 sc->sc_indirect = false;
137} 137}
138 138
139 139
140/* 140/*
141 * Device configuration registers readers/writers 141 * Device configuration registers readers/writers
142 */ 142 */
143#if 0 143#if 0
144#define DPRINTFR(n, fmt, val, index, num) \ 144#define DPRINTFR(n, fmt, val, index, num) \
145 printf("\n%s (", n); \ 145 printf("\n%s (", n); \
146 for (int i = 0; i < num; i++) \ 146 for (int i = 0; i < num; i++) \
147 printf("%02x ", bus_space_read_1(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index+i)); \ 147 printf("%02x ", bus_space_read_1(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index+i)); \
148 printf(") -> "); printf(fmt, val); printf("\n"); 148 printf(") -> "); printf(fmt, val); printf("\n");
 149#define DPRINTFR2(n, fmt, val_s, val_n) \
 150 printf("%s ", n); \
 151 printf("\n stream "); printf(fmt, val_s); printf(" norm "); printf(fmt, val_n); printf("\n");
149#else 152#else
150#define DPRINTFR(n, fmt, val, index, num) 153#define DPRINTFR(n, fmt, val, index, num)
 154#define DPRINTFR2(n, fmt, val_s, val_n)
151#endif 155#endif
152 156
 157
153uint8_t 158uint8_t
154virtio_read_device_config_1(struct virtio_softc *sc, int index) { 159virtio_read_device_config_1(struct virtio_softc *sc, int index) {
 160 bus_space_tag_t iot = sc->sc_devcfg_iot;
 161 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
155 uint8_t val; 162 uint8_t val;
156 val = sc->sc_ops->read_dev_cfg_1(sc, index); 163
 164 val = bus_space_read_1(iot, ioh, index);
 165
157 DPRINTFR("read_1", "%02x", val, index, 1); 166 DPRINTFR("read_1", "%02x", val, index, 1);
158 return val; 167 return val;
159} 168}
160 169
161uint16_t 170uint16_t
162virtio_read_device_config_2(struct virtio_softc *sc, int index) { 171virtio_read_device_config_2(struct virtio_softc *sc, int index) {
 172 bus_space_tag_t iot = sc->sc_devcfg_iot;
 173 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
163 uint16_t val; 174 uint16_t val;
164 val = sc->sc_ops->read_dev_cfg_2(sc, index); 175
 176 val = bus_space_read_2(iot, ioh, index);
 177 if (BYTE_ORDER != sc->sc_bus_endian)
 178 val = bswap16(val);
 179
165 DPRINTFR("read_2", "%04x", val, index, 2); 180 DPRINTFR("read_2", "%04x", val, index, 2);
 181 DPRINTFR2("read_2", "%04x",
 182 bus_space_read_stream_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index),
 183 bus_space_read_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index));
166 return val; 184 return val;
167} 185}
168 186
169uint32_t 187uint32_t
170virtio_read_device_config_4(struct virtio_softc *sc, int index) { 188virtio_read_device_config_4(struct virtio_softc *sc, int index) {
 189 bus_space_tag_t iot = sc->sc_devcfg_iot;
 190 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
171 uint32_t val; 191 uint32_t val;
172 val = sc->sc_ops->read_dev_cfg_4(sc, index); 192
 193 val = bus_space_read_4(iot, ioh, index);
 194 if (BYTE_ORDER != sc->sc_bus_endian)
 195 val = bswap32(val);
 196
173 DPRINTFR("read_4", "%08x", val, index, 4); 197 DPRINTFR("read_4", "%08x", val, index, 4);
 198 DPRINTFR2("read_4", "%08x",
 199 bus_space_read_stream_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index),
 200 bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index));
174 return val; 201 return val;
175} 202}
176 203
177uint64_t 204uint64_t
178virtio_read_device_config_8(struct virtio_softc *sc, int index) { 205virtio_read_device_config_8(struct virtio_softc *sc, int index) {
179 uint64_t val; 206 bus_space_tag_t iot = sc->sc_devcfg_iot;
180 val = sc->sc_ops->read_dev_cfg_8(sc, index); 207 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
 208 uint64_t val, val_0, val_1, val_l, val_h;
 209
 210 val_0 = bus_space_read_4(iot, ioh, index);
 211 val_1 = bus_space_read_4(iot, ioh, index + 4);
 212 if (BYTE_ORDER != sc->sc_bus_endian) {
 213 val_l = bswap32(val_1);
 214 val_h = bswap32(val_0);
 215 } else {
 216 val_l = val_0;
 217 val_h = val_1;
 218 }
 219
 220#ifdef AARCH64EB_PROBLEM
 221 /* XXX see comment at virtio_pci.c */
 222 if (sc->sc_aarch64eb_bus_problem) {
 223 val_l = val_1;
 224 val_h = val_0;
 225 }
 226#endif
 227
 228 val = val_h << 32;
 229 val |= val_l;
 230
181 DPRINTFR("read_8", "%08lx", val, index, 8); 231 DPRINTFR("read_8", "%08lx", val, index, 8);
 232 DPRINTFR2("read_8 low ", "%08x",
 233 bus_space_read_stream_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index),
 234 bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index));
 235 DPRINTFR2("read_8 high ", "%08x",
 236 bus_space_read_stream_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index + 4),
 237 bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, index + 4));
182 return val; 238 return val;
183} 239}
184 240
185/* 241/*
186 * In the older virtio spec, device config registers are host endian. On newer 242 * In the older virtio spec, device config registers are host endian. On newer
187 * they are little endian. The normal logic will cater for this. However some 243 * they are little endian. Some newer devices however explicitly specify their
188 * devices however explicitly state that its fields are always little endian 244 * register to always be little endian. These fuctions cater for these.
189 * and will still need to be swapped. 
190 */ 245 */
191uint16_t 246uint16_t
192virtio_read_device_config_le_2(struct virtio_softc *sc, int index) { 247virtio_read_device_config_le_2(struct virtio_softc *sc, int index) {
193 bool virtio_v1 = (sc->sc_active_features & VIRTIO_F_VERSION_1); 248 bus_space_tag_t iot = sc->sc_devcfg_iot;
 249 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
194 uint16_t val; 250 uint16_t val;
195 251
196 val = sc->sc_ops->read_dev_cfg_2(sc, index); 252 val = bus_space_read_2(iot, ioh, index);
197 val = virtio_v1 ? val : le16toh(val); 253 if (sc->sc_bus_endian != LITTLE_ENDIAN)
198 DPRINTFR("read_le_2", "%08x", val, index, 2); 254 val = bswap16(val);
 255
 256 DPRINTFR("read_le_2", "%04x", val, index, 2);
 257 DPRINTFR2("read_le_2", "%04x",
 258 bus_space_read_stream_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, 0),
 259 bus_space_read_2(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, 0));
199 return val; 260 return val;
200} 261}
201 262
202uint32_t 263uint32_t
203virtio_read_device_config_le_4(struct virtio_softc *sc, int index) { 264virtio_read_device_config_le_4(struct virtio_softc *sc, int index) {
204 bool virtio_v1 = (sc->sc_active_features & VIRTIO_F_VERSION_1); 265 bus_space_tag_t iot = sc->sc_devcfg_iot;
 266 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
205 uint32_t val; 267 uint32_t val;
206 268
207 val = sc->sc_ops->read_dev_cfg_4(sc, index); 269 val = bus_space_read_4(iot, ioh, index);
208 val = virtio_v1 ? val : le32toh(val); 270 if (sc->sc_bus_endian != LITTLE_ENDIAN)
 271 val = bswap32(val);
 272
209 DPRINTFR("read_le_4", "%08x", val, index, 4); 273 DPRINTFR("read_le_4", "%08x", val, index, 4);
 274 DPRINTFR2("read_le_4", "%08x",
 275 bus_space_read_stream_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, 0),
 276 bus_space_read_4(sc->sc_devcfg_iot, sc->sc_devcfg_ioh, 0));
210 return val; 277 return val;
211} 278}
212 279
213void 280void
214virtio_write_device_config_1(struct virtio_softc *sc, int index, uint8_t value) 281virtio_write_device_config_1(struct virtio_softc *sc, int index, uint8_t value)
215{ 282{
216 sc->sc_ops->write_dev_cfg_1(sc, index, value); 283 bus_space_tag_t iot = sc->sc_devcfg_iot;
 284 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
 285
 286 bus_space_write_1(iot, ioh, index, value);
217} 287}
218 288
219void 289void
220virtio_write_device_config_2(struct virtio_softc *sc, int index, uint16_t value) 290virtio_write_device_config_2(struct virtio_softc *sc, int index, uint16_t value)
221{ 291{
222 sc->sc_ops->write_dev_cfg_2(sc, index, value); 292 bus_space_tag_t iot = sc->sc_devcfg_iot;
 293 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
 294
 295 if (BYTE_ORDER != sc->sc_bus_endian)
 296 value = bswap16(value);
 297 bus_space_write_2(iot, ioh, index, value);
223} 298}
224 299
225void 300void
226virtio_write_device_config_4(struct virtio_softc *sc, int index, uint32_t value) 301virtio_write_device_config_4(struct virtio_softc *sc, int index, uint32_t value)
227{ 302{
228 sc->sc_ops->write_dev_cfg_4(sc, index, value); 303 bus_space_tag_t iot = sc->sc_devcfg_iot;
 304 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
 305
 306 if (BYTE_ORDER != sc->sc_bus_endian)
 307 value = bswap32(value);
 308 bus_space_write_4(iot, ioh, index, value);
229} 309}
230 310
231void 311void
232virtio_write_device_config_8(struct virtio_softc *sc, int index, uint64_t value) 312virtio_write_device_config_8(struct virtio_softc *sc, int index, uint64_t value)
233{ 313{
234 sc->sc_ops->write_dev_cfg_8(sc, index, value); 314 bus_space_tag_t iot = sc->sc_devcfg_iot;
 315 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
 316 uint64_t val_0, val_1, val_l, val_h;
 317
 318 val_l = BUS_ADDR_LO32(value);
 319 val_h = BUS_ADDR_HI32(value);
 320
 321 if (BYTE_ORDER != sc->sc_bus_endian) {
 322 val_0 = bswap32(val_h);
 323 val_1 = bswap32(val_l);
 324 } else {
 325 val_0 = val_l;
 326 val_1 = val_h;
 327 }
 328
 329#ifdef AARCH64EB_PROBLEM
 330 /* XXX see comment at virtio_pci.c */
 331 if (sc->sc_aarch64eb_bus_problem) {
 332 val_0 = val_h;
 333 val_1 = val_l;
 334 }
 335#endif
 336
 337 bus_space_write_4(iot, ioh, index, val_0);
 338 bus_space_write_4(iot, ioh, index + 4, val_1);
235} 339}
236 340
237/* 341/*
238 * In the older virtio spec, device config registers are host endian. On newer 342 * In the older virtio spec, device config registers are host endian. On newer
239 * they are little endian. The normal logic will cater for this. However some 343 * they are little endian. Some newer devices however explicitly specify their
240 * devices however explicitly state that its fields are always little endian 344 * register to always be little endian. These fuctions cater for these.
241 * and will still need to be swapped. 
242 */ 345 */
243void 346void
244virtio_write_device_config_le_2(struct virtio_softc *sc, int index, uint16_t value) 347virtio_write_device_config_le_2(struct virtio_softc *sc, int index, uint16_t value)
245{ 348{
246 bool virtio_v1 = (sc->sc_active_features & VIRTIO_F_VERSION_1); 349 bus_space_tag_t iot = sc->sc_devcfg_iot;
247 value = virtio_v1 ? value : htole16(value); 350 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
248 sc->sc_ops->write_dev_cfg_2(sc, index, value); 351
 352 if (sc->sc_bus_endian != LITTLE_ENDIAN)
 353 value = bswap16(value);
 354 bus_space_write_2(iot, ioh, index, value);
249} 355}
250 356
251void 357void
252virtio_write_device_config_le_4(struct virtio_softc *sc, int index, uint32_t value) 358virtio_write_device_config_le_4(struct virtio_softc *sc, int index, uint32_t value)
253{ 359{
254 bool virtio_v1 = (sc->sc_active_features & VIRTIO_F_VERSION_1); 360 bus_space_tag_t iot = sc->sc_devcfg_iot;
255 value = virtio_v1 ? value : htole32(value); 361 bus_space_handle_t ioh = sc->sc_devcfg_ioh;
256 sc->sc_ops->write_dev_cfg_4(sc, index, value); 362
 363 if (sc->sc_bus_endian != LITTLE_ENDIAN)
 364 value = bswap32(value);
 365 bus_space_write_4(iot, ioh, index, value);
257} 366}
258 367
 368
259/* 369/*
260 * data structures endian helpers 370 * data structures endian helpers
261 */ 371 */
262uint16_t virtio_rw16(struct virtio_softc *sc, uint16_t val) 372uint16_t virtio_rw16(struct virtio_softc *sc, uint16_t val)
263{ 373{
264 KASSERT(sc); 374 KASSERT(sc);
265 return (sc->sc_devcfg_swap) ? bswap16(val) : val; 375 return BYTE_ORDER != sc->sc_struct_endian ? bswap16(val) : val;
266} 376}
267 377
268uint32_t virtio_rw32(struct virtio_softc *sc, uint32_t val) 378uint32_t virtio_rw32(struct virtio_softc *sc, uint32_t val)
269{ 379{
270 KASSERT(sc); 380 KASSERT(sc);
271 return (sc->sc_devcfg_swap) ? bswap32(val) : val; 381 return BYTE_ORDER != sc->sc_struct_endian ? bswap32(val) : val;
272} 382}
273 383
274uint64_t virtio_rw64(struct virtio_softc *sc, uint64_t val) 384uint64_t virtio_rw64(struct virtio_softc *sc, uint64_t val)
275{ 385{
276 KASSERT(sc); 386 KASSERT(sc);
277 return (sc->sc_devcfg_swap) ? bswap64(val) : val; 387 return BYTE_ORDER != sc->sc_struct_endian ? bswap64(val) : val;
278} 388}
279 389
280 390
281/* 391/*
282 * Interrupt handler. 392 * Interrupt handler.
283 */ 393 */
284static void 394static void
285virtio_soft_intr(void *arg) 395virtio_soft_intr(void *arg)
286{ 396{
287 struct virtio_softc *sc = arg; 397 struct virtio_softc *sc = arg;
288 398
289 KASSERT(sc->sc_intrhand != NULL); 399 KASSERT(sc->sc_intrhand != NULL);
290 400

cvs diff -r1.26 -r1.27 src/sys/dev/pci/virtio_pci.c (expand / switch to unified diff)

--- src/sys/dev/pci/virtio_pci.c 2021/01/26 16:40:16 1.26
+++ src/sys/dev/pci/virtio_pci.c 2021/01/28 15:43:12 1.27
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: virtio_pci.c,v 1.26 2021/01/26 16:40:16 reinoud Exp $ */ 1/* $NetBSD: virtio_pci.c,v 1.27 2021/01/28 15:43:12 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * Copyright (c) 2012 Stefan Fritsch. 5 * Copyright (c) 2012 Stefan Fritsch.
6 * Copyright (c) 2010 Minoura Makoto. 6 * Copyright (c) 2010 Minoura Makoto.
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -18,27 +18,27 @@ @@ -18,27 +18,27 @@
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 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 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 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 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 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. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.26 2021/01/26 16:40:16 reinoud Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.27 2021/01/28 15:43:12 reinoud Exp $");
32 32
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/kmem.h> 35#include <sys/kmem.h>
36#include <sys/module.h> 36#include <sys/module.h>
37#include <sys/endian.h> 37#include <sys/endian.h>
38#include <sys/interrupt.h> 38#include <sys/interrupt.h>
39 39
40#include <sys/device.h> 40#include <sys/device.h>
41 41
42#include <dev/pci/pcidevs.h> 42#include <dev/pci/pcidevs.h>
43#include <dev/pci/pcireg.h> 43#include <dev/pci/pcireg.h>
44#include <dev/pci/pcivar.h> 44#include <dev/pci/pcivar.h>
@@ -96,145 +96,88 @@ static void virtio_pci_kick_09(struct vi @@ -96,145 +96,88 @@ static void virtio_pci_kick_09(struct vi
96static uint16_t virtio_pci_read_queue_size_09(struct virtio_softc *, uint16_t); 96static uint16_t virtio_pci_read_queue_size_09(struct virtio_softc *, uint16_t);
97static void virtio_pci_setup_queue_09(struct virtio_softc *, uint16_t, uint64_t); 97static void virtio_pci_setup_queue_09(struct virtio_softc *, uint16_t, uint64_t);
98static void virtio_pci_set_status_09(struct virtio_softc *, int); 98static void virtio_pci_set_status_09(struct virtio_softc *, int);
99static void virtio_pci_negotiate_features_09(struct virtio_softc *, uint64_t); 99static void virtio_pci_negotiate_features_09(struct virtio_softc *, uint64_t);
100 100
101static int virtio_pci_attach_10(device_t, void *); 101static int virtio_pci_attach_10(device_t, void *);
102static void virtio_pci_kick_10(struct virtio_softc *, uint16_t); 102static void virtio_pci_kick_10(struct virtio_softc *, uint16_t);
103static uint16_t virtio_pci_read_queue_size_10(struct virtio_softc *, uint16_t); 103static uint16_t virtio_pci_read_queue_size_10(struct virtio_softc *, uint16_t);
104static void virtio_pci_setup_queue_10(struct virtio_softc *, uint16_t, uint64_t); 104static void virtio_pci_setup_queue_10(struct virtio_softc *, uint16_t, uint64_t);
105static void virtio_pci_set_status_10(struct virtio_softc *, int); 105static void virtio_pci_set_status_10(struct virtio_softc *, int);
106static void virtio_pci_negotiate_features_10(struct virtio_softc *, uint64_t); 106static void virtio_pci_negotiate_features_10(struct virtio_softc *, uint64_t);
107static int virtio_pci_find_cap(struct virtio_pci_softc *psc, int cfg_type, void *buf, int buflen); 107static int virtio_pci_find_cap(struct virtio_pci_softc *psc, int cfg_type, void *buf, int buflen);
108 108
109static uint8_t virtio_pci_read_device_config_1(struct virtio_softc *, int); 
110static uint16_t virtio_pci_read_device_config_2(struct virtio_softc *, int); 
111static uint32_t virtio_pci_read_device_config_4(struct virtio_softc *, int); 
112static uint64_t virtio_pci_read_device_config_8(struct virtio_softc *, int); 
113static void virtio_pci_write_device_config_1(struct virtio_softc *, int, uint8_t); 
114static void virtio_pci_write_device_config_2(struct virtio_softc *, int, uint16_t); 
115static void virtio_pci_write_device_config_4(struct virtio_softc *, int, uint32_t); 
116static void virtio_pci_write_device_config_8(struct virtio_softc *, int, uint64_t); 
117 
118static int virtio_pci_setup_interrupts(struct virtio_softc *); 109static int virtio_pci_setup_interrupts(struct virtio_softc *);
119static void virtio_pci_free_interrupts(struct virtio_softc *); 110static void virtio_pci_free_interrupts(struct virtio_softc *);
120static int virtio_pci_adjust_config_region(struct virtio_pci_softc *psc); 111static int virtio_pci_adjust_config_region(struct virtio_pci_softc *psc);
121static int virtio_pci_intr(void *arg); 112static int virtio_pci_intr(void *arg);
122static int virtio_pci_msix_queue_intr(void *); 113static int virtio_pci_msix_queue_intr(void *);
123static int virtio_pci_msix_config_intr(void *); 114static int virtio_pci_msix_config_intr(void *);
124static int virtio_pci_setup_msix_vectors_09(struct virtio_softc *); 115static int virtio_pci_setup_msix_vectors_09(struct virtio_softc *);
125static int virtio_pci_setup_msix_vectors_10(struct virtio_softc *); 116static int virtio_pci_setup_msix_vectors_10(struct virtio_softc *);
126static int virtio_pci_setup_msix_interrupts(struct virtio_softc *, 117static int virtio_pci_setup_msix_interrupts(struct virtio_softc *,
127 struct pci_attach_args *); 118 struct pci_attach_args *);
128static int virtio_pci_setup_intx_interrupt(struct virtio_softc *, 119static int virtio_pci_setup_intx_interrupt(struct virtio_softc *,
129 struct pci_attach_args *); 120 struct pci_attach_args *);
130 121
131#define VIRTIO_MSIX_CONFIG_VECTOR_INDEX 0 122#define VIRTIO_MSIX_CONFIG_VECTOR_INDEX 0
132#define VIRTIO_MSIX_QUEUE_VECTOR_INDEX 1 123#define VIRTIO_MSIX_QUEUE_VECTOR_INDEX 1
133 124
134#if 0 125/*
135/* we use the legacy virtio spec, so the PCI registers are host native 126 * When using PCI attached virtio on aarch64-eb under Qemu, the IO space
136 * byte order, not PCI (i.e. LE) byte order */ 127 * suddenly read BIG_ENDIAN where it should stay LITTLE_ENDIAN. The data read
137#if BYTE_ORDER == BIG_ENDIAN 128 * 1 byte at a time seem OK but reading bigger lengths result in swapped
138#define REG_HI_OFF 0 129 * endian. This is most notable on reading 8 byters since we can't use
139#define REG_LO_OFF 4 130 * bus_space_{read,write}_8() and it has to be patched there explicitly. We
140#ifndef __BUS_SPACE_HAS_STREAM_METHODS 131 * define the AARCH64EB_PROBLEM to signal we're vulnerable to this and set the
141#define bus_space_read_stream_1 bus_space_read_1 132 * accompanied sc->sc_aarch64_eb_bus_problem variable when attaching using the
142#define bus_space_write_stream_1 bus_space_write_1 133 * IO space.
143static inline uint16_t 134 */
144bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, 
145 bus_size_t o) 
146{ 
147 return le16toh(bus_space_read_2(t, h, o)); 
148} 
149static inline void 
150bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, 
151 bus_size_t o, uint16_t v) 
152{ 
153 bus_space_write_2(t, h, o, htole16(v)); 
154} 
155static inline uint32_t 
156bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, 
157 bus_size_t o) 
158{ 
159 return le32toh(bus_space_read_4(t, h, o)); 
160} 
161static inline void 
162bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, 
163 bus_size_t o, uint32_t v) 
164{ 
165 bus_space_write_4(t, h, o, htole32(v)); 
166} 
167#endif 
168#else 
169#define REG_HI_OFF 4 
170#define REG_LO_OFF 0 
171#ifndef __BUS_SPACE_HAS_STREAM_METHODS 
172#define bus_space_read_stream_1 bus_space_read_1 
173#define bus_space_read_stream_2 bus_space_read_2 
174#define bus_space_read_stream_4 bus_space_read_4 
175#define bus_space_write_stream_1 bus_space_write_1 
176#define bus_space_write_stream_2 bus_space_write_2 
177#define bus_space_write_stream_4 bus_space_write_4 
178#endif 
179#endif 
180#endif 
181 
182 135
183#if BYTE_ORDER == LITTLE_ENDIAN 136#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN
184# define VIODEVRW_SWAP_09 false  137 /* source of AARCH64EB_PROBLEM */
185# define VIODEVRW_SWAP_10 false 138# define READ_ENDIAN_09 BIG_ENDIAN /* XXX bug, should be LITTLE_ENDIAN */
186#else /* big endian */ 139# define READ_ENDIAN_10 BIG_ENDIAN
187# define VIODEVRW_SWAP_09 false 140# define STRUCT_ENDIAN_09 BIG_ENDIAN
188# define VIODEVRW_SWAP_10 true 141# define STRUCT_ENDIAN_10 LITTLE_ENDIAN
 142#elif BYTE_ORDER == BIG_ENDIAN
 143# define READ_ENDIAN_09 LITTLE_ENDIAN
 144# define READ_ENDIAN_10 BIG_ENDIAN
 145# define STRUCT_ENDIAN_09 BIG_ENDIAN
 146# define STRUCT_ENDIAN_10 LITTLE_ENDIAN
 147#else /* little endian */
 148# define READ_ENDIAN_09 LITTLE_ENDIAN
 149# define READ_ENDIAN_10 LITTLE_ENDIAN
 150# define STRUCT_ENDIAN_09 LITTLE_ENDIAN
 151# define STRUCT_ENDIAN_10 LITTLE_ENDIAN
189#endif 152#endif
190 153
191 154
192CFATTACH_DECL3_NEW(virtio_pci, sizeof(struct virtio_pci_softc), 155CFATTACH_DECL3_NEW(virtio_pci, sizeof(struct virtio_pci_softc),
193 virtio_pci_match, virtio_pci_attach, virtio_pci_detach, NULL, 156 virtio_pci_match, virtio_pci_attach, virtio_pci_detach, NULL,
194 virtio_pci_rescan, NULL, DVF_DETACH_SHUTDOWN); 157 virtio_pci_rescan, NULL, DVF_DETACH_SHUTDOWN);
195 158
196static const struct virtio_ops virtio_pci_ops_09 = { 159static const struct virtio_ops virtio_pci_ops_09 = {
197 .kick = virtio_pci_kick_09, 160 .kick = virtio_pci_kick_09,
198 
199 .read_dev_cfg_1 = virtio_pci_read_device_config_1, 
200 .read_dev_cfg_2 = virtio_pci_read_device_config_2, 
201 .read_dev_cfg_4 = virtio_pci_read_device_config_4, 
202 .read_dev_cfg_8 = virtio_pci_read_device_config_8, 
203 .write_dev_cfg_1 = virtio_pci_write_device_config_1, 
204 .write_dev_cfg_2 = virtio_pci_write_device_config_2, 
205 .write_dev_cfg_4 = virtio_pci_write_device_config_4, 
206 .write_dev_cfg_8 = virtio_pci_write_device_config_8, 
207 
208 .read_queue_size = virtio_pci_read_queue_size_09, 161 .read_queue_size = virtio_pci_read_queue_size_09,
209 .setup_queue = virtio_pci_setup_queue_09, 162 .setup_queue = virtio_pci_setup_queue_09,
210 .set_status = virtio_pci_set_status_09, 163 .set_status = virtio_pci_set_status_09,
211 .neg_features = virtio_pci_negotiate_features_09, 164 .neg_features = virtio_pci_negotiate_features_09,
212 .setup_interrupts = virtio_pci_setup_interrupts, 165 .setup_interrupts = virtio_pci_setup_interrupts,
213 .free_interrupts = virtio_pci_free_interrupts, 166 .free_interrupts = virtio_pci_free_interrupts,
214}; 167};
215 168
216static const struct virtio_ops virtio_pci_ops_10 = { 169static const struct virtio_ops virtio_pci_ops_10 = {
217 .kick = virtio_pci_kick_10, 170 .kick = virtio_pci_kick_10,
218 
219 .read_dev_cfg_1 = virtio_pci_read_device_config_1, 
220 .read_dev_cfg_2 = virtio_pci_read_device_config_2, 
221 .read_dev_cfg_4 = virtio_pci_read_device_config_4, 
222 .read_dev_cfg_8 = virtio_pci_read_device_config_8, 
223 .write_dev_cfg_1 = virtio_pci_write_device_config_1, 
224 .write_dev_cfg_2 = virtio_pci_write_device_config_2, 
225 .write_dev_cfg_4 = virtio_pci_write_device_config_4, 
226 .write_dev_cfg_8 = virtio_pci_write_device_config_8, 
227 
228 .read_queue_size = virtio_pci_read_queue_size_10, 171 .read_queue_size = virtio_pci_read_queue_size_10,
229 .setup_queue = virtio_pci_setup_queue_10, 172 .setup_queue = virtio_pci_setup_queue_10,
230 .set_status = virtio_pci_set_status_10, 173 .set_status = virtio_pci_set_status_10,
231 .neg_features = virtio_pci_negotiate_features_10, 174 .neg_features = virtio_pci_negotiate_features_10,
232 .setup_interrupts = virtio_pci_setup_interrupts, 175 .setup_interrupts = virtio_pci_setup_interrupts,
233 .free_interrupts = virtio_pci_free_interrupts, 176 .free_interrupts = virtio_pci_free_interrupts,
234}; 177};
235 178
236static int 179static int
237virtio_pci_match(device_t parent, cfdata_t match, void *aux) 180virtio_pci_match(device_t parent, cfdata_t match, void *aux)
238{ 181{
239 struct pci_attach_args *pa; 182 struct pci_attach_args *pa;
240 183
@@ -414,27 +357,31 @@ virtio_pci_attach_09(device_t self, void @@ -414,27 +357,31 @@ virtio_pci_attach_09(device_t self, void
414 psc->sc_notify_iot = psc->sc_iot; 357 psc->sc_notify_iot = psc->sc_iot;
415 358
416 /* ISR space */ 359 /* ISR space */
417 if (bus_space_subregion(psc->sc_iot, psc->sc_ioh, 360 if (bus_space_subregion(psc->sc_iot, psc->sc_ioh,
418 VIRTIO_CONFIG_ISR_STATUS, 1, &psc->sc_isr_ioh)) { 361 VIRTIO_CONFIG_ISR_STATUS, 1, &psc->sc_isr_ioh)) {
419 aprint_error_dev(self, "can't map isr i/o space\n"); 362 aprint_error_dev(self, "can't map isr i/o space\n");
420 return EIO; 363 return EIO;
421 } 364 }
422 psc->sc_isr_iosize = 1; 365 psc->sc_isr_iosize = 1;
423 psc->sc_isr_iot = psc->sc_iot; 366 psc->sc_isr_iot = psc->sc_iot;
424 367
425 /* set our version 0.9 ops */ 368 /* set our version 0.9 ops */
426 sc->sc_ops = &virtio_pci_ops_09; 369 sc->sc_ops = &virtio_pci_ops_09;
427 sc->sc_devcfg_swap = VIODEVRW_SWAP_09; 370 sc->sc_bus_endian = READ_ENDIAN_09;
 371 sc->sc_struct_endian = STRUCT_ENDIAN_09;
 372#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN
 373 sc->sc_aarch64eb_bus_problem = true;
 374#endif
428 return 0; 375 return 0;
429} 376}
430 377
431 378
432static int 379static int
433virtio_pci_attach_10(device_t self, void *aux) 380virtio_pci_attach_10(device_t self, void *aux)
434{ 381{
435 struct virtio_pci_softc * const psc = device_private(self); 382 struct virtio_pci_softc * const psc = device_private(self);
436 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 383 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
437 struct virtio_softc * const sc = &psc->sc_sc; 384 struct virtio_softc * const sc = &psc->sc_sc;
438 pci_chipset_tag_t pc = pa->pa_pc; 385 pci_chipset_tag_t pc = pa->pa_pc;
439 pcitag_t tag = pa->pa_tag; 386 pcitag_t tag = pa->pa_tag;
440 387
@@ -535,27 +482,28 @@ virtio_pci_attach_10(device_t self, void @@ -535,27 +482,28 @@ virtio_pci_attach_10(device_t self, void
535 common.offset, common.length, &psc->sc_ioh)) { 482 common.offset, common.length, &psc->sc_ioh)) {
536 aprint_error_dev(self, "can't map common i/o space\n"); 483 aprint_error_dev(self, "can't map common i/o space\n");
537 ret = EIO; 484 ret = EIO;
538 goto err; 485 goto err;
539 } 486 }
540 psc->sc_iosize = common.length; 487 psc->sc_iosize = common.length;
541 psc->sc_iot = psc->sc_bars_iot[i]; 488 psc->sc_iot = psc->sc_bars_iot[i];
542 psc->sc_mapped_iosize = psc->sc_bars_iosize[i]; 489 psc->sc_mapped_iosize = psc->sc_bars_iosize[i];
543 490
544 psc->sc_sc.sc_version_1 = 1; 491 psc->sc_sc.sc_version_1 = 1;
545 492
546 /* set our version 1.0 ops */ 493 /* set our version 1.0 ops */
547 sc->sc_ops = &virtio_pci_ops_10; 494 sc->sc_ops = &virtio_pci_ops_10;
548 sc->sc_devcfg_swap = VIODEVRW_SWAP_10; 495 sc->sc_bus_endian = READ_ENDIAN_10;
 496 sc->sc_struct_endian = STRUCT_ENDIAN_10;
549 return 0; 497 return 0;
550 498
551err: 499err:
552 /* undo our pci_mapreg_map()s */  500 /* undo our pci_mapreg_map()s */
553 for (i = 0; i < __arraycount(bars); i++) { 501 for (i = 0; i < __arraycount(bars); i++) {
554 if (psc->sc_bars_iosize[i] == 0) 502 if (psc->sc_bars_iosize[i] == 0)
555 continue; 503 continue;
556 bus_space_unmap(psc->sc_bars_iot[i], psc->sc_bars_ioh[i], 504 bus_space_unmap(psc->sc_bars_iot[i], psc->sc_bars_ioh[i],
557 psc->sc_bars_iosize[i]); 505 psc->sc_bars_iosize[i]);
558 } 506 }
559 return ret; 507 return ret;
560} 508}
561 509
@@ -845,186 +793,26 @@ virtio_pci_negotiate_features_10(struct  @@ -845,186 +793,26 @@ virtio_pci_negotiate_features_10(struct
845 } 793 }
846 794
847 if ((negotiated & VIRTIO_F_VERSION_1) == 0) { 795 if ((negotiated & VIRTIO_F_VERSION_1) == 0) {
848 aprint_error_dev(self, "host rejected version 1\n"); 796 aprint_error_dev(self, "host rejected version 1\n");
849 bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS, 797 bus_space_write_1(iot, ioh, VIRTIO_CONFIG1_DEVICE_STATUS,
850 VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 798 VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
851 return; 799 return;
852 } 800 }
853 801
854 sc->sc_active_features = negotiated; 802 sc->sc_active_features = negotiated;
855 return; 803 return;
856} 804}
857 805
858/* ------------------------------------- 
859 * Read/write device config code 
860 * -------------------------------------*/ 
861 
862static uint8_t 
863virtio_pci_read_device_config_1(struct virtio_softc *vsc, int index) 
864{ 
865 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
866 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
867 
868 return bus_space_read_1(iot, ioh, index); 
869} 
870 
871static uint16_t 
872virtio_pci_read_device_config_2(struct virtio_softc *vsc, int index) 
873{ 
874 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
875 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
876 uint16_t val; 
877 
878#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
879 val = bus_space_read_2(iot, ioh, index); 
880 return val; 
881#else 
882 val = bus_space_read_stream_2(iot, ioh, index); 
883 if (vsc->sc_devcfg_swap) 
884 return bswap16(val); 
885 return val; 
886#endif 
887} 
888 
889static uint32_t 
890virtio_pci_read_device_config_4(struct virtio_softc *vsc, int index) 
891{ 
892 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
893 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
894 uint32_t val; 
895 
896#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
897 val = bus_space_read_4(iot, ioh, index); 
898 return val; 
899#else 
900 val = bus_space_read_stream_4(iot, ioh, index); 
901 if (vsc->sc_devcfg_swap) 
902 return bswap32(val); 
903 return val; 
904#endif 
905} 
906 
907static uint64_t 
908virtio_pci_read_device_config_8(struct virtio_softc *vsc, int index) 
909{ 
910 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
911 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
912 uint64_t val, val_h, val_l; 
913 
914#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
915 if (vsc->sc_devcfg_swap) { 
916 val_l = bus_space_read_4(iot, ioh, index); 
917 val_h = bus_space_read_4(iot, ioh, index + 4); 
918 } else { 
919 val_h = bus_space_read_4(iot, ioh, index); 
920 val_l = bus_space_read_4(iot, ioh, index + 4); 
921 } 
922 val = val_h << 32; 
923 val |= val_l; 
924 return val; 
925#elif BYTE_ORDER == BIG_ENDIAN 
926 val_h = bus_space_read_stream_4(iot, ioh, index); 
927 val_l = bus_space_read_stream_4(iot, ioh, index + 4); 
928 val = val_h << 32; 
929 val |= val_l; 
930 if (vsc->sc_devcfg_swap) 
931 return bswap64(val); 
932 return val; 
933#else 
934 val_l = bus_space_read_4(iot, ioh, index); 
935 val_h = bus_space_read_4(iot, ioh, index + 4); 
936 val = val_h << 32; 
937 val |= val_l; 
938 
939 return val; 
940#endif 
941} 
942 
943static void 
944virtio_pci_write_device_config_1(struct virtio_softc *vsc, 
945 int index, uint8_t value) 
946{ 
947 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
948 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
949 
950 bus_space_write_1(iot, ioh, index, value); 
951} 
952 
953static void 
954virtio_pci_write_device_config_2(struct virtio_softc *vsc, 
955 int index, uint16_t value) 
956{ 
957 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
958 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
959 
960#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
961 bus_space_write_2(iot, ioh, index, value); 
962#else 
963 if (vsc->sc_devcfg_swap) 
964 value = bswap16(value); 
965 bus_space_write_stream_2(iot, ioh, index, value); 
966#endif 
967} 
968 
969static void 
970virtio_pci_write_device_config_4(struct virtio_softc *vsc, 
971 int index, uint32_t value) 
972{ 
973 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
974 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
975 
976#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
977 bus_space_write_4(iot, ioh, index, value); 
978#else 
979 if (vsc->sc_devcfg_swap) 
980 value = bswap32(value); 
981 bus_space_write_stream_4(iot, ioh, index, value); 
982#endif 
983} 
984 
985static void 
986virtio_pci_write_device_config_8(struct virtio_softc *vsc, 
987 int index, uint64_t value) 
988{ 
989 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
990 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
991 uint64_t val_h, val_l; 
992 
993#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 
994 val_l = value & 0xffffffff; 
995 val_h = value >> 32; 
996 if (vsc->sc_devcfg_swap) { 
997 bus_space_write_4(iot, ioh, index, val_l); 
998 bus_space_write_4(iot, ioh, index + 4, val_h); 
999 } else { 
1000 bus_space_write_4(iot, ioh, index, val_h); 
1001 bus_space_write_4(iot, ioh, index + 4, val_l); 
1002 } 
1003#elif BYTE_ORDER == BIG_ENDIAN 
1004 if (vsc->sc_devcfg_swap) 
1005 value = bswap64(value); 
1006 val_l = value & 0xffffffff; 
1007 val_h = value >> 32; 
1008 
1009 bus_space_write_stream_4(iot, ioh, index, val_h); 
1010 bus_space_write_stream_4(iot, ioh, index + 4, val_l); 
1011#else 
1012 val_l = value & 0xffffffff; 
1013 val_h = value >> 32; 
1014 bus_space_write_stream_4(iot, ioh, index, val_l); 
1015 bus_space_write_stream_4(iot, ioh, index + 4, val_h); 
1016#endif 
1017} 
1018 806
1019/* ------------------------------------- 807/* -------------------------------------
1020 * Generic PCI interrupt code 808 * Generic PCI interrupt code
1021 * -------------------------------------*/ 809 * -------------------------------------*/
1022 810
1023static int 811static int
1024virtio_pci_setup_msix_vectors_10(struct virtio_softc *sc) 812virtio_pci_setup_msix_vectors_10(struct virtio_softc *sc)
1025{ 813{
1026 struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc; 814 struct virtio_pci_softc * const psc = (struct virtio_pci_softc *)sc;
1027 device_t self = sc->sc_dev; 815 device_t self = sc->sc_dev;
1028 bus_space_tag_t iot = psc->sc_iot; 816 bus_space_tag_t iot = psc->sc_iot;
1029 bus_space_handle_t ioh = psc->sc_ioh; 817 bus_space_handle_t ioh = psc->sc_ioh;
1030 int vector, ret, qid; 818 int vector, ret, qid;

cvs diff -r1.18 -r1.19 src/sys/dev/pci/virtiovar.h (expand / switch to unified diff)

--- src/sys/dev/pci/virtiovar.h 2021/01/20 21:59:48 1.18
+++ src/sys/dev/pci/virtiovar.h 2021/01/28 15:43:12 1.19
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: virtiovar.h,v 1.18 2021/01/20 21:59:48 reinoud Exp $ */ 1/* $NetBSD: virtiovar.h,v 1.19 2021/01/28 15:43:12 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 Minoura Makoto. 4 * Copyright (c) 2010 Minoura Makoto.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -125,50 +125,45 @@ struct virtqueue { @@ -125,50 +125,45 @@ struct virtqueue {
125 /* for 1.0 */ 125 /* for 1.0 */
126 uint32_t vq_notify_off; 126 uint32_t vq_notify_off;
127}; 127};
128 128
129struct virtio_attach_args { 129struct virtio_attach_args {
130 int sc_childdevid; 130 int sc_childdevid;
131}; 131};
132 132
133typedef int (*virtio_callback)(struct virtio_softc*); 133typedef int (*virtio_callback)(struct virtio_softc*);
134 134
135#ifdef VIRTIO_PRIVATE 135#ifdef VIRTIO_PRIVATE
136struct virtio_ops { 136struct virtio_ops {
137 void (*kick)(struct virtio_softc *, uint16_t); 137 void (*kick)(struct virtio_softc *, uint16_t);
138 
139 uint8_t (*read_dev_cfg_1)(struct virtio_softc *, int); 
140 uint16_t (*read_dev_cfg_2)(struct virtio_softc *, int); 
141 uint32_t (*read_dev_cfg_4)(struct virtio_softc *, int); 
142 uint64_t (*read_dev_cfg_8)(struct virtio_softc *, int); 
143 void (*write_dev_cfg_1)(struct virtio_softc *, int, uint8_t); 
144 void (*write_dev_cfg_2)(struct virtio_softc *, int, uint16_t); 
145 void (*write_dev_cfg_4)(struct virtio_softc *, int, uint32_t); 
146 void (*write_dev_cfg_8)(struct virtio_softc *, int, uint64_t); 
147 
148 uint16_t (*read_queue_size)(struct virtio_softc *, uint16_t); 138 uint16_t (*read_queue_size)(struct virtio_softc *, uint16_t);
149 void (*setup_queue)(struct virtio_softc *, uint16_t, uint64_t); 139 void (*setup_queue)(struct virtio_softc *, uint16_t, uint64_t);
150 void (*set_status)(struct virtio_softc *, int); 140 void (*set_status)(struct virtio_softc *, int);
151 void (*neg_features)(struct virtio_softc *, uint64_t); 141 void (*neg_features)(struct virtio_softc *, uint64_t);
152 int (*setup_interrupts)(struct virtio_softc *); 142 int (*setup_interrupts)(struct virtio_softc *);
153 void (*free_interrupts)(struct virtio_softc *); 143 void (*free_interrupts)(struct virtio_softc *);
154}; 144};
155 145
156struct virtio_softc { 146struct virtio_softc {
157 device_t sc_dev; 147 device_t sc_dev;
158 const struct virtio_ops *sc_ops; 148 const struct virtio_ops *sc_ops;
159 bus_dma_tag_t sc_dmat; 149 bus_dma_tag_t sc_dmat;
160 150
161 bool sc_devcfg_swap; 151#define AARCH64EB_PROBLEM /* see comment in virtio_pci.c */
 152 bool sc_aarch64eb_bus_problem;
 153
 154 int sc_bus_endian;
 155 int sc_struct_endian;
 156
162 bus_space_tag_t sc_devcfg_iot; 157 bus_space_tag_t sc_devcfg_iot;
163 bus_space_handle_t sc_devcfg_ioh; 158 bus_space_handle_t sc_devcfg_ioh;
164 bus_size_t sc_devcfg_iosize; 159 bus_size_t sc_devcfg_iosize;
165 160
166 int sc_ipl; /* set by child */ 161 int sc_ipl; /* set by child */
167 void *sc_soft_ih; 162 void *sc_soft_ih;
168 163
169 int sc_flags; /* set by child */ 164 int sc_flags; /* set by child */
170 165
171 uint64_t sc_active_features; 166 uint64_t sc_active_features;
172 bool sc_indirect; 167 bool sc_indirect;
173 bool sc_version_1; 168 bool sc_version_1;
174 bool sc_finished_called; 169 bool sc_finished_called;

cvs diff -r1.4 -r1.5 src/sys/dev/virtio/virtio_mmio.c (expand / switch to unified diff)

--- src/sys/dev/virtio/virtio_mmio.c 2021/01/20 19:46:48 1.4
+++ src/sys/dev/virtio/virtio_mmio.c 2021/01/28 15:43:13 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: virtio_mmio.c,v 1.4 2021/01/20 19:46:48 reinoud Exp $ */ 1/* $NetBSD: virtio_mmio.c,v 1.5 2021/01/28 15:43:13 reinoud Exp $ */
2/* $OpenBSD: virtio_mmio.c,v 1.2 2017/02/24 17:12:31 patrick Exp $ */ 2/* $OpenBSD: virtio_mmio.c,v 1.2 2017/02/24 17:12:31 patrick Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> 5 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
6 * Copyright (c) 2012 Stefan Fritsch. 6 * Copyright (c) 2012 Stefan Fritsch.
7 * Copyright (c) 2010 Minoura Makoto. 7 * Copyright (c) 2010 Minoura Makoto.
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.4 2021/01/20 19:46:48 reinoud Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.5 2021/01/28 15:43:13 reinoud Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/systm.h> 35#include <sys/systm.h>
36#include <sys/kernel.h> 36#include <sys/kernel.h>
37#include <sys/device.h> 37#include <sys/device.h>
38#include <sys/mutex.h> 38#include <sys/mutex.h>
39 39
40#define VIRTIO_PRIVATE 40#define VIRTIO_PRIVATE
41#include <dev/virtio/virtio_mmiovar.h> 41#include <dev/virtio/virtio_mmiovar.h>
42 42
43#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) 43#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)
44 44
45#define VIRTIO_MMIO_MAGIC_VALUE 0x000 45#define VIRTIO_MMIO_MAGIC_VALUE 0x000
@@ -58,82 +58,53 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio. @@ -58,82 +58,53 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio.
58#define VIRTIO_MMIO_QUEUE_PFN 0x040 58#define VIRTIO_MMIO_QUEUE_PFN 0x040
59#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 59#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050
60#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 60#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060
61#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 61#define VIRTIO_MMIO_INTERRUPT_ACK 0x064
62#define VIRTIO_MMIO_STATUS 0x070 62#define VIRTIO_MMIO_STATUS 0x070
63#define VIRTIO_MMIO_CONFIG 0x100 63#define VIRTIO_MMIO_CONFIG 0x100
64 64
65#define VIRTIO_MMIO_INT_VRING (1 << 0) 65#define VIRTIO_MMIO_INT_VRING (1 << 0)
66#define VIRTIO_MMIO_INT_CONFIG (1 << 1) 66#define VIRTIO_MMIO_INT_CONFIG (1 << 1)
67 67
68/* 68/*
69 * MMIO configuration space for virtio-mmio v1 is in guest byte order. 69 * MMIO configuration space for virtio-mmio v1 is in guest byte order.
70 * 70 *
71 * AArch64 BE is special in that its bus space functions always read little 71 * XXX Note that aarch64eb pretends to be little endian. the MMIO registers
72 * endian like on the PCI bus and thus need swapping to read host endian 72 * are in little endian but the device config registers and data structures
73 * registers. 73 * are in big endian; this is due to a bug in current Qemu.
74 * 
75 * XXX this might also be true for other big endian machines. 
76 * XXX: TODO test virtio MMIO on non AArch64 big endian machines. 
77 */ 74 */
78 75
79#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN 76#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN
80#define VIO16TOH(x) le16toh(x) 77# define READ_ENDIAN LITTLE_ENDIAN
81#define VIO32TOH(x) le32toh(x) 78# define STRUCT_ENDIAN BIG_ENDIAN
82#define VIO64TOH(x) le64toh(x) 79#elif BYTE_ORDER == BIG_ENDIAN
83#define HTOVIO16(x) htole16(x) 80# define READ_ENDIAN BIG_ENDIAN
84#define HTOVIO32(x) htole32(x) 81# define STRUCT_ENDIAN BIG_ENDIAN
85#define HTOVIO64(x) htole64(x) 
86#define VIODEVRW_SWAP false /* can only be native endian now */ 
87#else 82#else
88#define VIO16TOH(x) (x) 83# define READ_ENDIAN LITTLE_ENDIAN
89#define VIO32TOH(x) (x) 84# define STRUCT_ENDIAN LITTLE_ENDIAN
90#define VIO64TOH(x) (x) 
91#define HTOVIO16(x) (x) 
92#define HTOVIO32(x) (x) 
93#define HTOVIO64(x) (x) 
94#define VIODEVRW_SWAP false /* will only be native endian now */ 
95#endif 85#endif
96 86
97 87
98static void virtio_mmio_kick(struct virtio_softc *, uint16_t); 88static void virtio_mmio_kick(struct virtio_softc *, uint16_t);
99static uint8_t virtio_mmio_read_device_config_1(struct virtio_softc *, int); 
100static uint16_t virtio_mmio_read_device_config_2(struct virtio_softc *, int); 
101static uint32_t virtio_mmio_read_device_config_4(struct virtio_softc *, int); 
102static uint64_t virtio_mmio_read_device_config_8(struct virtio_softc *, int); 
103static void virtio_mmio_write_device_config_1(struct virtio_softc *, int, uint8_t); 
104static void virtio_mmio_write_device_config_2(struct virtio_softc *, int, uint16_t); 
105static void virtio_mmio_write_device_config_4(struct virtio_softc *, int, uint32_t); 
106static void virtio_mmio_write_device_config_8(struct virtio_softc *, int, uint64_t); 
107 
108static uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t); 89static uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t);
109static void virtio_mmio_setup_queue(struct virtio_softc *, uint16_t, uint64_t); 90static void virtio_mmio_setup_queue(struct virtio_softc *, uint16_t, uint64_t);
110static void virtio_mmio_set_status(struct virtio_softc *, int); 91static void virtio_mmio_set_status(struct virtio_softc *, int);
111static void virtio_mmio_negotiate_features(struct virtio_softc *, uint64_t); 92static void virtio_mmio_negotiate_features(struct virtio_softc *, uint64_t);
112static int virtio_mmio_setup_interrupts(struct virtio_softc *); 93static int virtio_mmio_setup_interrupts(struct virtio_softc *);
113static void virtio_mmio_free_interrupts(struct virtio_softc *); 94static void virtio_mmio_free_interrupts(struct virtio_softc *);
114 95
115static const struct virtio_ops virtio_mmio_ops = { 96static const struct virtio_ops virtio_mmio_ops = {
116 .kick = virtio_mmio_kick, 97 .kick = virtio_mmio_kick,
117 
118 .read_dev_cfg_1 = virtio_mmio_read_device_config_1, 
119 .read_dev_cfg_2 = virtio_mmio_read_device_config_2, 
120 .read_dev_cfg_4 = virtio_mmio_read_device_config_4, 
121 .read_dev_cfg_8 = virtio_mmio_read_device_config_8, 
122 .write_dev_cfg_1 = virtio_mmio_write_device_config_1, 
123 .write_dev_cfg_2 = virtio_mmio_write_device_config_2, 
124 .write_dev_cfg_4 = virtio_mmio_write_device_config_4, 
125 .write_dev_cfg_8 = virtio_mmio_write_device_config_8, 
126 
127 .read_queue_size = virtio_mmio_read_queue_size, 98 .read_queue_size = virtio_mmio_read_queue_size,
128 .setup_queue = virtio_mmio_setup_queue, 99 .setup_queue = virtio_mmio_setup_queue,
129 .set_status = virtio_mmio_set_status, 100 .set_status = virtio_mmio_set_status,
130 .neg_features = virtio_mmio_negotiate_features, 101 .neg_features = virtio_mmio_negotiate_features,
131 .setup_interrupts = virtio_mmio_setup_interrupts, 102 .setup_interrupts = virtio_mmio_setup_interrupts,
132 .free_interrupts = virtio_mmio_free_interrupts, 103 .free_interrupts = virtio_mmio_free_interrupts,
133}; 104};
134 105
135static uint16_t 106static uint16_t
136virtio_mmio_read_queue_size(struct virtio_softc *vsc, uint16_t idx) 107virtio_mmio_read_queue_size(struct virtio_softc *vsc, uint16_t idx)
137{ 108{
138 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 109 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc;
139 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, idx); 110 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, idx);
@@ -192,27 +163,28 @@ virtio_mmio_common_attach(struct virtio_ @@ -192,27 +163,28 @@ virtio_mmio_common_attach(struct virtio_
192 163
193 id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_DEVICE_ID); 164 id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_DEVICE_ID);
194 165
195 /* we could use PAGE_SIZE, but virtio(4) assumes 4KiB for now */ 166 /* we could use PAGE_SIZE, but virtio(4) assumes 4KiB for now */
196 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_GUEST_PAGE_SIZE, 167 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_GUEST_PAGE_SIZE,
197 VIRTIO_PAGE_SIZE); 168 VIRTIO_PAGE_SIZE);
198 169
199 /* no device connected. */ 170 /* no device connected. */
200 if (id == 0) 171 if (id == 0)
201 return; 172 return;
202 173
203 virtio_print_device_type(self, id, ver); 174 virtio_print_device_type(self, id, ver);
204 vsc->sc_ops = &virtio_mmio_ops; 175 vsc->sc_ops = &virtio_mmio_ops;
205 vsc->sc_devcfg_swap = VIODEVRW_SWAP; 176 vsc->sc_bus_endian = READ_ENDIAN;
 177 vsc->sc_struct_endian = STRUCT_ENDIAN;
206 178
207 /* set up our device config tag */ 179 /* set up our device config tag */
208 vsc->sc_devcfg_iosize = sc->sc_iosize - VIRTIO_MMIO_CONFIG; 180 vsc->sc_devcfg_iosize = sc->sc_iosize - VIRTIO_MMIO_CONFIG;
209 vsc->sc_devcfg_iot = sc->sc_iot; 181 vsc->sc_devcfg_iot = sc->sc_iot;
210 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 182 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
211 VIRTIO_MMIO_CONFIG, vsc->sc_devcfg_iosize, 183 VIRTIO_MMIO_CONFIG, vsc->sc_devcfg_iosize,
212 &vsc->sc_devcfg_ioh)) { 184 &vsc->sc_devcfg_ioh)) {
213 aprint_error_dev(self, "can't map config i/o space\n"); 185 aprint_error_dev(self, "can't map config i/o space\n");
214 return; 186 return;
215 } 187 }
216 188
217 virtio_device_reset(vsc); 189 virtio_device_reset(vsc);
218 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 190 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
@@ -259,120 +231,26 @@ virtio_mmio_negotiate_features(struct vi @@ -259,120 +231,26 @@ virtio_mmio_negotiate_features(struct vi
259 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 231 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
260 VIRTIO_MMIO_HOST_FEATURES_SEL, 0); 232 VIRTIO_MMIO_HOST_FEATURES_SEL, 0);
261 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 233 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
262 VIRTIO_MMIO_HOST_FEATURES); 234 VIRTIO_MMIO_HOST_FEATURES);
263 r &= guest_features; 235 r &= guest_features;
264 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 236 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
265 VIRTIO_MMIO_GUEST_FEATURES_SEL, 0); 237 VIRTIO_MMIO_GUEST_FEATURES_SEL, 0);
266 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 238 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
267 VIRTIO_MMIO_GUEST_FEATURES, r); 239 VIRTIO_MMIO_GUEST_FEATURES, r);
268 240
269 vsc->sc_active_features = r; 241 vsc->sc_active_features = r;
270} 242}
271 243
272# 
273/* 
274 * Device configuration registers. 
275 */ 
276 
277/* ---------------------------------------------------- 
278 * Read/write device config code 
279 * ----------------------------------------------------*/ 
280 
281static uint8_t 
282virtio_mmio_read_device_config_1(struct virtio_softc *vsc, int index) 
283{ 
284 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
285 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
286 
287 return bus_space_read_1(iot, ioh, index); 
288} 
289 
290static uint16_t 
291virtio_mmio_read_device_config_2(struct virtio_softc *vsc, int index) 
292{ 
293 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
294 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
295 
296 return VIO16TOH(bus_space_read_2(iot, ioh, index)); 
297} 
298 
299static uint32_t 
300virtio_mmio_read_device_config_4(struct virtio_softc *vsc, int index) 
301{ 
302 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
303 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
304 
305 return VIO32TOH(bus_space_read_4(iot, ioh, index)); 
306} 
307 
308static uint64_t 
309virtio_mmio_read_device_config_8(struct virtio_softc *vsc, int index) 
310{ 
311 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
312 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
313 uint64_t r; 
314 
315 r = bus_space_read_4(iot, ioh, index + sizeof(uint32_t)); 
316 r <<= 32; 
317 r += bus_space_read_4(iot, ioh, index); 
318 return VIO64TOH(r); 
319} 
320 
321static void 
322virtio_mmio_write_device_config_1(struct virtio_softc *vsc, 
323 int index, uint8_t value) 
324{ 
325 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
326 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
327 
328 bus_space_write_1(iot, ioh, index, value); 
329} 
330 
331static void 
332virtio_mmio_write_device_config_2(struct virtio_softc *vsc, 
333 int index, uint16_t value) 
334{ 
335 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
336 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
337 
338 value = HTOVIO16(value); 
339 bus_space_write_2(iot, ioh, index, value); 
340} 
341 
342static void 
343virtio_mmio_write_device_config_4(struct virtio_softc *vsc, 
344 int index, uint32_t value) 
345{ 
346 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
347 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
348 
349 value = HTOVIO32(value); 
350 bus_space_write_4(iot, ioh, index, value); 
351} 
352 
353static void 
354virtio_mmio_write_device_config_8(struct virtio_softc *vsc, 
355 int index, uint64_t value) 
356{ 
357 bus_space_tag_t iot = vsc->sc_devcfg_iot; 
358 bus_space_handle_t ioh = vsc->sc_devcfg_ioh; 
359 
360 value = HTOVIO64(value); 
361 bus_space_write_4(iot, ioh, index, value & 0xffffffff); 
362 bus_space_write_4(iot, ioh, index + sizeof(uint32_t), value >> 32); 
363} 
364 
365 
366/* 244/*
367 * Interrupt handler. 245 * Interrupt handler.
368 */ 246 */
369int 247int
370virtio_mmio_intr(void *arg) 248virtio_mmio_intr(void *arg)
371{ 249{
372 struct virtio_mmio_softc *sc = arg; 250 struct virtio_mmio_softc *sc = arg;
373 struct virtio_softc *vsc = &sc->sc_sc; 251 struct virtio_softc *vsc = &sc->sc_sc;
374 int isr, r = 0; 252 int isr, r = 0;
375 253
376 /* check and ack the interrupt */ 254 /* check and ack the interrupt */
377 isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 255 isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
378 VIRTIO_MMIO_INTERRUPT_STATUS); 256 VIRTIO_MMIO_INTERRUPT_STATUS);