sparc: Use big endian packet accessors.
[gem5.git] / src / dev / virtio / base.hh
1 /*
2 * Copyright (c) 2014, 2016-2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40 #ifndef __DEV_VIRTIO_BASE_HH__
41 #define __DEV_VIRTIO_BASE_HH__
42
43 #include "arch/isa_traits.hh"
44 #include "base/bitunion.hh"
45 #include "base/callback.hh"
46 #include "dev/virtio/virtio_ring.h"
47 #include "mem/port_proxy.hh"
48 #include "sim/sim_object.hh"
49
50 struct VirtIODeviceBaseParams;
51 struct VirtIODummyDeviceParams;
52
53 class VirtQueue;
54
55 /** @{
56 * @name VirtIO endian conversion helpers
57 *
58 * VirtIO prior to version 1.0 (legacy versions) normally send values
59 * to the host in the guest systems native byte order. This is going
60 * to change in version 1.0 which mandates little endian. We currently
61 * only support the legacy version of VirtIO (the new and shiny
62 * standard is still in a draft state and not implemented by the
63 * kernel). Once we support the new standard, we should negotiate the
64 * VirtIO version with the guest and automatically use the right type
65 * of byte swapping.
66 */
67
68 /** Convert legacy VirtIO endianness to host endianness. */
69 template <typename T> inline T
70 vtoh_legacy(T v) {
71 return TheISA::gtoh(v);
72 }
73
74 /** Convert host endianness to legacy VirtIO endianness. */
75 template <typename T> inline T
76 htov_legacy(T v) {
77 return TheISA::htog(v);
78 }
79
80
81 template <> inline vring_used_elem
82 vtoh_legacy(vring_used_elem v) {
83 v.id = vtoh_legacy(v.id);
84 v.len = vtoh_legacy(v.len);
85 return v;
86 }
87
88 template <> inline vring_used_elem
89 htov_legacy(vring_used_elem v) {
90 v.id = htov_legacy(v.id);
91 v.len = htov_legacy(v.len);
92 return v;
93 }
94
95 template <> inline vring_desc
96 vtoh_legacy(vring_desc v) {
97 v.addr = vtoh_legacy(v.addr);
98 v.len = vtoh_legacy(v.len);
99 v.flags = vtoh_legacy(v.flags);
100 v.next = vtoh_legacy(v.next);
101 return v;
102 }
103
104 template <> inline vring_desc
105 htov_legacy(vring_desc v) {
106 v.addr = htov_legacy(v.addr);
107 v.len = htov_legacy(v.len);
108 v.flags = htov_legacy(v.flags);
109 v.next = htov_legacy(v.next);
110 return v;
111 }
112
113 /** @} */
114
115 /**
116 * VirtIO descriptor (chain) wrapper
117 *
118 * Communication in VirtIO takes place by sending and receiving chains
119 * of so called descriptors using device queues. The queue is
120 * responsible for sending a descriptor chain from the guest to the
121 * host and later sending it back to the guest. The descriptor chain
122 * itself can be thought of as a linked list of buffers (descriptors)
123 * that are read only (isIncoming() is true) or write only
124 * (isOutgoing() is true). A single chain may contain any mix of input
125 * and output buffers.
126 *
127 * The descriptor wrapper is normally <i>only</i> instantiated by the
128 * virtqueue wrapper (VirtQueue) and should never be instantiated in
129 * device models. The VirtQueue also ensures that the descriptor
130 * wrapper is re-populated with new data from the guest by calling
131 * updateChain() whenever a new descriptor chain is passed to the host
132 * (VirtQueue::consumeDescriptor()). The updateChain() method
133 * automatically does some sanity checks on the descriptor chain to
134 * detect loops.
135 */
136 class VirtDescriptor
137 {
138 public:
139 /** Descriptor index in virtqueue */
140 typedef uint16_t Index;
141
142 /** @{
143 * @name VirtIO Descriptor <-> Queue Interface
144 */
145 /**
146 * Create a descriptor wrapper.
147 *
148 * @param memProxy Proxy to the guest physical memory.
149 * @param queue Queue owning this descriptor.
150 * @param index Index within the queue.
151 */
152 VirtDescriptor(PortProxy &memProxy, VirtQueue &queue, Index index);
153 // WORKAROUND: The noexcept declaration works around a bug where
154 // gcc 4.7 tries to call the wrong constructor when emplacing
155 // something into a vector.
156 VirtDescriptor(VirtDescriptor &&other) noexcept;
157 ~VirtDescriptor() noexcept;
158
159 VirtDescriptor &operator=(VirtDescriptor &&rhs) noexcept;
160
161 /** Get the descriptor's index into the virtqueue. */
162 Index index() const { return _index; }
163
164 /** Populate this descriptor with data from the guest. */
165 void update();
166
167 /** Populate this descriptor chain with data from the guest. */
168 void updateChain();
169 /** @} */
170
171 /** @{
172 * @name Debug interfaces
173 */
174 /**
175 * Dump the contents of a descriptor
176 */
177 void dump() const;
178 /**
179 * Dump the contents of a descriptor chain starting at this
180 * descriptor.
181 */
182 void dumpChain() const;
183 /** @} */
184
185
186 /** @{
187 * @name Device Model Interfaces
188 */
189 /**
190 * Read the contents of a descriptor.
191 *
192 * This method copies the contents of a descriptor into a buffer
193 * within gem5. Devices should typically use chainRead() instead
194 * as it automatically follows the descriptor chain to read the
195 * desired number of bytes.
196 *
197 * @see chainRead
198 *
199 * @param offset Offset into the descriptor.
200 * @param dst Destination buffer.
201 * @param size Amount of data to read (in bytes).
202 */
203 void read(size_t offset, uint8_t *dst, size_t size) const;
204 /**
205 * Write to the contents of a descriptor.
206 *
207 * This method copies the contents of a descriptor into a buffer
208 * within gem5. Devices should typically use chainWrite() instead
209 * as it automatically follows the descriptor chain to read the
210 * desired number of bytes.
211 *
212 * @see chainWrite
213 *
214 * @param offset Offset into the descriptor.
215 * @param src Source buffer.
216 * @param size Amount of data to read (in bytes).
217 */
218 void write(size_t offset, const uint8_t *src, size_t size);
219 /**
220 * Retrieve the size of this descriptor.
221 *
222 * This method gets the size of a single descriptor. For incoming
223 * data, it corresponds to the amount of data that can be read
224 * from the descriptor. For outgoing data, it corresponds to the
225 * amount of data that can be written to it.
226 *
227 * @see chainSize
228 *
229 * @return Size of descriptor in bytes.
230 */
231 size_t size() const { return desc.len; }
232
233 /**
234 * Is this descriptor chained to another descriptor?
235 *
236 * @return true if there is a next pointer, false otherwise.
237 */
238 bool hasNext() const { return desc.flags & VRING_DESC_F_NEXT; }
239 /**
240 * Get the pointer to the next descriptor in a chain.
241 *
242 * @return Pointer to the next descriptor or NULL if this is the
243 * last element in a chain.
244 */
245 VirtDescriptor *next() const;
246
247 /** Check if this is a read-only descriptor (incoming data). */
248 bool isIncoming() const { return !isOutgoing(); }
249 /** Check if this is a write-only descriptor (outgoing data). */
250 bool isOutgoing() const { return desc.flags & VRING_DESC_F_WRITE; }
251
252
253 /**
254 * Read the contents of a descriptor chain.
255 *
256 * This method reads the specified number of bytes from a
257 * descriptor chain starting at the this descriptor plus an offset
258 * in bytes. The method automatically follows the links in the
259 * descriptor chain.
260 *
261 * @param offset Offset into the chain (in bytes).
262 * @param dst Pointer to destination buffer.
263 * @param size Size (in bytes).
264 */
265 void chainRead(size_t offset, uint8_t *dst, size_t size) const;
266 /**
267 * Write to a descriptor chain.
268 *
269 * This method writes the specified number of bytes to a
270 * descriptor chain starting at the this descriptor plus an offset
271 * in bytes. The method automatically follows the links in the
272 * descriptor chain.
273 *
274 * @param offset Offset into the chain (in bytes).
275 * @param src Pointer to source buffer.
276 * @param size Size (in bytes).
277 */
278 void chainWrite(size_t offset, const uint8_t *src, size_t size);
279 /**
280 * Retrieve the size of this descriptor chain.
281 *
282 * This method gets the size of a descriptor chain starting at
283 * this descriptor.
284 *
285 * @return Size of descriptor chain in bytes.
286 */
287 size_t chainSize() const;
288 /** @} */
289
290 private:
291 // Remove default constructor
292 VirtDescriptor();
293 // Prevent copying
294 VirtDescriptor(const VirtDescriptor &other);
295
296 /** Pointer to memory proxy */
297 PortProxy *memProxy;
298 /** Pointer to virtqueue owning this descriptor */
299 VirtQueue *queue;
300
301 /** Index in virtqueue */
302 Index _index;
303
304 /** Underlying descriptor */
305 vring_desc desc;
306 };
307
308 /**
309 * Base wrapper around a virtqueue.
310 *
311 * VirtIO device models typically need to extend this class to
312 * implement their own device queues.
313 *
314 * @note Queues must be registered with
315 * VirtIODeviceBase::registerQueue() to be active.
316 */
317 class VirtQueue : public Serializable {
318 public:
319 virtual ~VirtQueue() {};
320
321 /** @{
322 * @name Checkpointing Interface
323 */
324 void serialize(CheckpointOut &cp) const override;
325 void unserialize(CheckpointIn &cp) override;
326
327 /** @{
328 * @name Low-level Device Interface
329 */
330 /**
331 * Set the base address of this queue.
332 *
333 * @param address Guest physical base address of the queue.
334 */
335 void setAddress(Addr address);
336 /**
337 * Get the guest physical address of this queue.
338 *
339 * @return Physical address in guest where this queue resides.
340 */
341 Addr getAddress() const { return _address; }
342
343 /**
344 * Get the number of descriptors available in this queue.
345 *
346 * @return Size of queue in descriptors.
347 */
348 uint16_t getSize() const { return _size; }
349
350 /**
351 * Get a pointer to a specific descriptor in the queue.
352 *
353 * @note This interfaces is normally only used by VirtDescriptor
354 * to follow descriptor chains. Device models typically don't need
355 * to use it.
356 *
357 * @return Pointer to a VirtDescriptor.
358 */
359 VirtDescriptor *getDescriptor(VirtDescriptor::Index index) {
360 return &descriptors[index];
361 }
362 /** @} */
363
364 /** @{
365 * @name Device Model Interfaces
366 */
367 /**
368 * Get an incoming descriptor chain from the queue.
369 *
370 * @return Pointer to descriptor on success, NULL if no pending
371 * descriptors are available.
372 */
373 VirtDescriptor *consumeDescriptor();
374 /**
375 * Send a descriptor chain to the guest.
376 *
377 * This method posts a descriptor chain to the guest after a
378 * device model has finished processing it. The device model
379 * typically needs to call VirtIODeviceBase::kick() to deliver
380 * notify tell the guest that the queue has been updated.
381 *
382 * @note The desc parameter must refer to the first descriptor in
383 * a chain that has been retrieved using consumeDescriptor().
384 *
385 * @note The len parameter specified the amount of data produced
386 * by the device model. It seems to be ignored by Linux and it is
387 * not well defined.
388 *
389 * @param desc Start of descriptor chain.
390 * @param len Length of the produced data.
391 */
392 void produceDescriptor(VirtDescriptor *desc, uint32_t len);
393 /** @} */
394
395 /** @{
396 * @name Device Model Callbacks
397 */
398 /**
399 * Notify queue of pending events.
400 *
401 * This method is called by VirtIODeviceBase::onNotify() to notify
402 * the device model of pending data in a virtqueue. The default
403 * implementation of this method iterates over the available
404 * descriptor chains and calls onNotifyDescriptor() for every new
405 * incoming chain.
406 *
407 * Device models should normally overload one of onNotify() and
408 * onNotifyDescriptor().
409 */
410 virtual void onNotify();
411 /**
412 * Notify queue of pending incoming descriptor.
413 *
414 * This method is called by the default implementation of
415 * onNotify() to notify the device model of pending data in a
416 * descriptor chain.
417 *
418 * Device models should normally overload one of onNotify() and
419 * onNotifyDescriptor().
420 */
421 virtual void onNotifyDescriptor(VirtDescriptor *desc) {};
422 /** @} */
423
424 /** @{
425 * @name Debug interfaces
426 */
427 /** Dump the contents of a queue */
428 void dump() const;
429 /** @} */
430
431 /** @{ */
432 /**
433 * Page size used by VirtIO.\ It's hard-coded to 4096 bytes in
434 * the spec for historical reasons.
435 */
436 static const Addr ALIGN_BITS = 12;
437 static const Addr ALIGN_SIZE = 1 << ALIGN_BITS;
438 /** @} */
439
440 protected:
441 /**
442 * Instantiate a new virtqueue.
443 *
444 * Instantiate a virtqueue with a fixed size. The size is
445 * specified in descriptors which are defined as 4096 bytes each.
446 *
447 * @param proxy Proxy to the guest physical memory.
448 * @param size Size in descriptors/pages.
449 */
450 VirtQueue(PortProxy &proxy, uint16_t size);
451
452 private:
453 VirtQueue();
454
455 /** Queue size in terms of number of descriptors */
456 const uint16_t _size;
457 /** Base address of the queue */
458 Addr _address;
459 /** Guest physical memory proxy */
460 PortProxy &memProxy;
461
462 private:
463 /**
464 * VirtIO ring buffer wrapper.
465 *
466 * This class wraps a VirtIO ring buffer. The template parameter T
467 * is used to select the data type for the items in the ring (used
468 * or available descriptors).
469 */
470 template<typename T>
471 class VirtRing
472 {
473 public:
474 typedef uint16_t Flags;
475 typedef uint16_t Index;
476
477 struct Header {
478 Flags flags;
479 Index index;
480 } M5_ATTR_PACKED;
481
482 VirtRing<T>(PortProxy &proxy, uint16_t size)
483 : header{0, 0}, ring(size), _proxy(proxy), _base(0) {}
484
485 /**
486 * Set the base address of the VirtIO ring buffer.
487 *
488 * @param addr New host physical address
489 */
490 void setAddress(Addr addr) { _base = addr; }
491
492 /** Update the ring buffer header with data from the guest. */
493 void readHeader() {
494 assert(_base != 0);
495 _proxy.readBlob(_base, (uint8_t *)&header, sizeof(header));
496 header.flags = vtoh_legacy(header.flags);
497 header.index = vtoh_legacy(header.index);
498 }
499
500 void writeHeader() {
501 Header out;
502 assert(_base != 0);
503 out.flags = htov_legacy(header.flags);
504 out.index = htov_legacy(header.index);
505 _proxy.writeBlob(_base, (uint8_t *)&out, sizeof(out));
506 }
507
508 void read() {
509 readHeader();
510
511 /* Read and byte-swap the elements in the ring */
512 T temp[ring.size()];
513 _proxy.readBlob(_base + sizeof(header),
514 (uint8_t *)temp, sizeof(T) * ring.size());
515 for (int i = 0; i < ring.size(); ++i)
516 ring[i] = vtoh_legacy(temp[i]);
517 }
518
519 void write() {
520 assert(_base != 0);
521 /* Create a byte-swapped copy of the ring and write it to
522 * guest memory. */
523 T temp[ring.size()];
524 for (int i = 0; i < ring.size(); ++i)
525 temp[i] = htov_legacy(ring[i]);
526 _proxy.writeBlob(_base + sizeof(header),
527 (uint8_t *)temp, sizeof(T) * ring.size());
528 writeHeader();
529 }
530
531 /** Ring buffer header in host byte order */
532 Header header;
533 /** Elements in ring in host byte order */
534 std::vector<T> ring;
535
536 private:
537 // Remove default constructor
538 VirtRing<T>();
539
540 /** Guest physical memory proxy */
541 PortProxy &_proxy;
542 /** Guest physical base address of the ring buffer */
543 Addr _base;
544 };
545
546 /** Ring of available (incoming) descriptors */
547 VirtRing<VirtDescriptor::Index> avail;
548 /** Ring of used (outgoing) descriptors */
549 VirtRing<struct vring_used_elem> used;
550
551 /** Offset of last consumed descriptor in the VirtQueue::avail
552 * ring */
553 uint16_t _last_avail;
554
555 /** Vector of pre-created descriptors indexed by their index into
556 * the queue. */
557 std::vector<VirtDescriptor> descriptors;
558 };
559
560 /**
561 * Base class for all VirtIO-based devices.
562 *
563 * This class implements the functionality of the VirtIO 0.9.5
564 * specification. This version of VirtIO is also known as "legacy" in
565 * the VirtIO 1.0 specification from OASIS.
566 *
567 * @see https://github.com/rustyrussell/virtio-spec
568 * @see http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html
569 */
570 class VirtIODeviceBase : public SimObject
571 {
572 public:
573 typedef uint16_t QueueID;
574 typedef uint32_t FeatureBits;
575 /** This is a VirtQueue address as exposed through the low-level
576 * interface.\ The address needs to be multiplied by the page size
577 * (seems to be hardcoded to 4096 in the spec) to get the real
578 * physical address.
579 */
580 typedef uint16_t VirtAddress;
581 /** Device Type (sometimes known as subsystem ID) */
582 typedef uint16_t DeviceId;
583
584 BitUnion8(DeviceStatus)
585 Bitfield<7> failed;
586 Bitfield<2> driver_ok;
587 Bitfield<1> driver;
588 Bitfield<0> acknowledge;
589 EndBitUnion(DeviceStatus)
590
591 typedef VirtIODeviceBaseParams Params;
592 VirtIODeviceBase(Params *params, DeviceId id, size_t config_size,
593 FeatureBits features);
594 virtual ~VirtIODeviceBase();
595
596 public:
597 /** @{
598 * @name SimObject Interfaces
599 */
600 void serialize(CheckpointOut &cp) const override;
601 void unserialize(CheckpointIn &cp) override;
602 /** @} */
603
604
605 protected:
606 /** @{
607 * @name Device Model Interfaces
608 */
609
610 /**
611 * Inform the guest of available buffers.
612 *
613 * When a device model has finished processing incoming buffers
614 * (after onNotify has been called), it typically needs to inform
615 * the guest that there are new pending outgoing buffers. The
616 * method used to inform the guest is transport dependent, but is
617 * typically through an interrupt. Device models call this method
618 * to tell the transport interface to notify the guest.
619 */
620 void kick() {
621 assert(transKick);
622 transKick->process();
623 };
624
625 /**
626 * Register a new VirtQueue with the device model.
627 *
628 * Devices typically register at least one VirtQueue to use for
629 * communication with the guest. This <i>must</i> be done from the
630 * constructor since the number of queues are assumed to be
631 * constant throughout the lifetime of the device.
632 *
633 * @warning This method may only be called from the device model
634 * constructor.
635 */
636 void registerQueue(VirtQueue &queue);
637
638
639 /**
640 * Feature set accepted by the guest.
641 *
642 * When the guest starts the driver for the device, it starts by
643 * negotiating features. The device first offers a set of features
644 * (see deviceFeatures), the driver then notifies the device of
645 * which features it accepted. The base class will automatically
646 * accept any feature set that is a subset of the features offered
647 * by the device.
648 */
649 FeatureBits guestFeatures;
650 /** @} */
651
652 public:
653 /** @{
654 * @name Optional VirtIO Interfaces
655 */
656 /**
657 * Read from the configuration space of a device.
658 *
659 * This method is called by the transport interface to read data
660 * from a device model's configuration space. The device model
661 * should use the cfgOffset parameter as the offset into its
662 * configuration space.
663 *
664 * @warning The address in the packet should not be used to
665 * determine the offset into a device's configuration space.
666 *
667 * @param pkt Read request packet.
668 * @param cfgOffset Offset into the device's configuration space.
669 */
670 virtual void readConfig(PacketPtr pkt, Addr cfgOffset);
671 /**
672 * Write to the configuration space of a device.
673 *
674 * This method is called by the transport interface to write data
675 * into a device model's configuration space. The device model
676 * should use the cfgOffset parameter as the offset into its
677 * configuration space.
678 *
679 * @warning The address in the packet should not be used to
680 * determine the offset into a device's configuration space.
681 *
682 * @param pkt Write request packet.
683 * @param cfgOffset Offset into the device's configuration space.
684 */
685 virtual void writeConfig(PacketPtr pkt, Addr cfgOffset);
686
687 /**
688 * Driver-request device reset.
689 *
690 * The device driver may reset a device by writing zero to the
691 * device status register (using setDeviceStatus()), which causes
692 * this method to be called. Device models overriding this method
693 * <i>must</i> ensure that the reset method of the base class is
694 * called when the device is reset.
695 *
696 * @note Always call the reset method of the base class from
697 * device-specific reset methods.
698 */
699 virtual void reset();
700 /** @} */
701
702 protected:
703 /** @{
704 * @name Device Model Helpers
705 */
706
707 /**
708 * Read configuration data from a device structure.
709 *
710 * @param pkt Read request packet.
711 * @param cfgOffset Offset into the device's configuration space.
712 * @param cfg Device configuration
713 */
714 void readConfigBlob(PacketPtr pkt, Addr cfgOffset, const uint8_t *cfg);
715
716 /**
717 * Write configuration data to a device structure.
718 *
719 * @param pkt Write request packet.
720 * @param cfgOffset Offset into the device's configuration space.
721 * @param cfg Device configuration
722 */
723 void writeConfigBlob(PacketPtr pkt, Addr cfgOffset, uint8_t *cfg);
724
725 /** @} */
726
727 public:
728 /** @{
729 * @name VirtIO Transport Interfaces
730 */
731 /**
732 * Register a callback to kick the guest through the transport
733 * interface.
734 *
735 * @param c Callback into transport interface.
736 */
737 void registerKickCallback(Callback *c) {
738 assert(!transKick);
739 transKick = c;
740 }
741
742
743 /**
744 * Driver is requesting service.
745 *
746 * This method is called by the underlying hardware interface
747 * (e.g., PciVirtIO or MmmioVirtIO) to notify a device of pending
748 * incoming descriptors.
749 *
750 * @param index ID of the queue with pending actions.
751 */
752 void onNotify(QueueID index);
753
754
755 /**
756 * Change currently active queue.
757 *
758 * The transport interface works on a queue at a time. The
759 * currently active queue is decided by the value of the queue
760 * select field in a device.
761 *
762 * @param idx ID of the queue to select.
763 */
764 void setQueueSelect(QueueID idx) { _queueSelect = idx; }
765 /**
766 * Get the currently active queue.
767 *
768 * The transport interface works on a queue at a time. The
769 * currently active queue is decided by the value of the queue
770 * select field in a device.
771 *
772 * @return The ID of the currently active queue.
773 */
774 QueueID getQueueSelect() const { return _queueSelect; }
775
776 /**
777 * Change the host physical address of the currently active queue.
778 *
779 * @note The new address is specified in multiples of the page
780 * size (fixed to 4096 bytes in the standard). For example, if the
781 * address 10 is selected, the actual host physical address will
782 * be 40960.
783 *
784 * @see setQueueSelect
785 * @see getQueueSelect
786 *
787 * @param address New address of the currently active queue (in
788 * pages).
789 */
790 void setQueueAddress(uint32_t address);
791 /**
792 * Get the host physical address of the currently active queue.
793 *
794 * @note The new address is specified in multiples of the page
795 * size (fixed to 4096 bytes in the standard). For example, if the
796 * address 10 is selected, the actual host physical address will
797 * be 40960.
798 *
799 * @see setQueueSelect
800 * @see getQueueSelect
801 *
802 * @return Address of the currently active queue (in pages).
803 */
804 uint32_t getQueueAddress() const;
805
806 /**
807 * Get the size (descriptors) of the currently active queue.
808 *
809 * @return Size of the currently active queue in number of
810 * descriptors.
811 */
812 uint16_t getQueueSize() const { return getCurrentQueue().getSize(); }
813
814 /**
815 * Update device status and optionally reset device.
816 *
817 * The special device status of 0 is used to reset the device by
818 * calling reset().
819 *
820 * @param status New device status.
821 */
822 void setDeviceStatus(DeviceStatus status);
823
824 /**
825 * Retrieve the device status.
826 *
827 * @return Device status.
828 */
829 DeviceStatus getDeviceStatus() const { return _deviceStatus; }
830
831 /**
832 * Set feature bits accepted by the guest driver.
833 *
834 * This enables a subset of the features offered by the device
835 * model through the getGuestFeatures() interface.
836 */
837 void setGuestFeatures(FeatureBits features);
838
839 /**
840 * Get features accepted by the guest driver.
841 *
842 * @return Currently active features.
843 */
844 FeatureBits getGuestFeatures() const { return guestFeatures; }
845
846 /** Device ID (sometimes known as subsystem ID) */
847 const DeviceId deviceId;
848
849 /** Size of the device's configuration space */
850 const size_t configSize;
851
852 /** Feature set offered by the device */
853 const FeatureBits deviceFeatures;
854 /** @} */
855
856 private:
857 /** Convenience method to get the currently selected queue */
858 const VirtQueue &getCurrentQueue() const;
859 /** Convenience method to get the currently selected queue */
860 VirtQueue &getCurrentQueue();
861
862 /**
863 * Status of the device
864 *
865 * @see getDeviceStatus
866 * @see setDeviceStatus
867 */
868 DeviceStatus _deviceStatus;
869
870 /** Queue select register (set by guest) */
871 QueueID _queueSelect;
872
873 /** List of virtual queues supported by this device */
874 std::vector<VirtQueue *> _queues;
875
876 /** Callbacks to kick the guest through the transport layer */
877 Callback *transKick;
878 };
879
880 class VirtIODummyDevice : public VirtIODeviceBase
881 {
882 public:
883 VirtIODummyDevice(VirtIODummyDeviceParams *params);
884
885 protected:
886 /** VirtIO device ID */
887 static const DeviceId ID_INVALID = 0x00;
888 };
889
890 #endif // __DEV_VIRTIO_BASE_HH__