2 * Copyright (c) 2014, 2016-2017 ARM Limited
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.
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.
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.
37 * Authors: Andreas Sandberg
40 #ifndef __DEV_VIRTIO_BASE_HH__
41 #define __DEV_VIRTIO_BASE_HH__
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"
50 struct VirtIODeviceBaseParams;
51 struct VirtIODummyDeviceParams;
56 * @name VirtIO endian conversion helpers
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
68 /** Convert legacy VirtIO endianness to host endianness. */
69 template <typename T> inline T
71 return TheISA::gtoh(v);
74 /** Convert host endianness to legacy VirtIO endianness. */
75 template <typename T> inline T
77 return TheISA::htog(v);
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);
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);
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);
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);
116 * VirtIO descriptor (chain) wrapper
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.
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
139 /** Descriptor index in virtqueue */
140 typedef uint16_t Index;
143 * @name VirtIO Descriptor <-> Queue Interface
146 * Create a descriptor wrapper.
148 * @param memProxy Proxy to the guest physical memory.
149 * @param queue Queue owning this descriptor.
150 * @param index Index within the queue.
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;
159 VirtDescriptor &operator=(VirtDescriptor &&rhs) noexcept;
161 /** Get the descriptor's index into the virtqueue. */
162 Index index() const { return _index; }
164 /** Populate this descriptor with data from the guest. */
167 /** Populate this descriptor chain with data from the guest. */
172 * @name Debug interfaces
175 * Dump the contents of a descriptor
179 * Dump the contents of a descriptor chain starting at this
182 void dumpChain() const;
187 * @name Device Model Interfaces
190 * Read the contents of a descriptor.
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.
199 * @param offset Offset into the descriptor.
200 * @param dst Destination buffer.
201 * @param size Amount of data to read (in bytes).
203 void read(size_t offset, uint8_t *dst, size_t size) const;
205 * Write to the contents of a descriptor.
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.
214 * @param offset Offset into the descriptor.
215 * @param src Source buffer.
216 * @param size Amount of data to read (in bytes).
218 void write(size_t offset, const uint8_t *src, size_t size);
220 * Retrieve the size of this descriptor.
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.
229 * @return Size of descriptor in bytes.
231 size_t size() const { return desc.len; }
234 * Is this descriptor chained to another descriptor?
236 * @return true if there is a next pointer, false otherwise.
238 bool hasNext() const { return desc.flags & VRING_DESC_F_NEXT; }
240 * Get the pointer to the next descriptor in a chain.
242 * @return Pointer to the next descriptor or NULL if this is the
243 * last element in a chain.
245 VirtDescriptor *next() const;
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; }
254 * Read the contents of a descriptor chain.
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
261 * @param offset Offset into the chain (in bytes).
262 * @param dst Pointer to destination buffer.
263 * @param size Size (in bytes).
265 void chainRead(size_t offset, uint8_t *dst, size_t size) const;
267 * Write to a descriptor chain.
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
274 * @param offset Offset into the chain (in bytes).
275 * @param src Pointer to source buffer.
276 * @param size Size (in bytes).
278 void chainWrite(size_t offset, const uint8_t *src, size_t size);
280 * Retrieve the size of this descriptor chain.
282 * This method gets the size of a descriptor chain starting at
285 * @return Size of descriptor chain in bytes.
287 size_t chainSize() const;
291 // Remove default constructor
294 VirtDescriptor(const VirtDescriptor &other);
296 /** Pointer to memory proxy */
298 /** Pointer to virtqueue owning this descriptor */
301 /** Index in virtqueue */
304 /** Underlying descriptor */
309 * Base wrapper around a virtqueue.
311 * VirtIO device models typically need to extend this class to
312 * implement their own device queues.
314 * @note Queues must be registered with
315 * VirtIODeviceBase::registerQueue() to be active.
317 class VirtQueue : public Serializable {
319 virtual ~VirtQueue() {};
322 * @name Checkpointing Interface
324 void serialize(CheckpointOut &cp) const override;
325 void unserialize(CheckpointIn &cp) override;
328 * @name Low-level Device Interface
331 * Set the base address of this queue.
333 * @param address Guest physical base address of the queue.
335 void setAddress(Addr address);
337 * Get the guest physical address of this queue.
339 * @return Physical address in guest where this queue resides.
341 Addr getAddress() const { return _address; }
344 * Get the number of descriptors available in this queue.
346 * @return Size of queue in descriptors.
348 uint16_t getSize() const { return _size; }
351 * Get a pointer to a specific descriptor in the queue.
353 * @note This interfaces is normally only used by VirtDescriptor
354 * to follow descriptor chains. Device models typically don't need
357 * @return Pointer to a VirtDescriptor.
359 VirtDescriptor *getDescriptor(VirtDescriptor::Index index) {
360 return &descriptors[index];
365 * @name Device Model Interfaces
368 * Get an incoming descriptor chain from the queue.
370 * @return Pointer to descriptor on success, NULL if no pending
371 * descriptors are available.
373 VirtDescriptor *consumeDescriptor();
375 * Send a descriptor chain to the guest.
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.
382 * @note The desc parameter must refer to the first descriptor in
383 * a chain that has been retrieved using consumeDescriptor().
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
389 * @param desc Start of descriptor chain.
390 * @param len Length of the produced data.
392 void produceDescriptor(VirtDescriptor *desc, uint32_t len);
396 * @name Device Model Callbacks
399 * Notify queue of pending events.
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
407 * Device models should normally overload one of onNotify() and
408 * onNotifyDescriptor().
410 virtual void onNotify();
412 * Notify queue of pending incoming descriptor.
414 * This method is called by the default implementation of
415 * onNotify() to notify the device model of pending data in a
418 * Device models should normally overload one of onNotify() and
419 * onNotifyDescriptor().
421 virtual void onNotifyDescriptor(VirtDescriptor *desc) {};
425 * @name Debug interfaces
427 /** Dump the contents of a queue */
433 * Page size used by VirtIO.\ It's hard-coded to 4096 bytes in
434 * the spec for historical reasons.
436 static const Addr ALIGN_BITS = 12;
437 static const Addr ALIGN_SIZE = 1 << ALIGN_BITS;
442 * Instantiate a new virtqueue.
444 * Instantiate a virtqueue with a fixed size. The size is
445 * specified in descriptors which are defined as 4096 bytes each.
447 * @param proxy Proxy to the guest physical memory.
448 * @param size Size in descriptors/pages.
450 VirtQueue(PortProxy &proxy, uint16_t size);
455 /** Queue size in terms of number of descriptors */
456 const uint16_t _size;
457 /** Base address of the queue */
459 /** Guest physical memory proxy */
464 * VirtIO ring buffer wrapper.
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).
474 typedef uint16_t Flags;
475 typedef uint16_t Index;
482 VirtRing<T>(PortProxy &proxy, uint16_t size)
483 : header{0, 0}, ring(size), _proxy(proxy), _base(0) {}
486 * Set the base address of the VirtIO ring buffer.
488 * @param addr New host physical address
490 void setAddress(Addr addr) { _base = addr; }
492 /** Update the ring buffer header with data from the guest. */
495 _proxy.readBlob(_base, (uint8_t *)&header, sizeof(header));
496 header.flags = vtoh_legacy(header.flags);
497 header.index = vtoh_legacy(header.index);
503 out.flags = htov_legacy(header.flags);
504 out.index = htov_legacy(header.index);
505 _proxy.writeBlob(_base, (uint8_t *)&out, sizeof(out));
511 /* Read and byte-swap the elements in the ring */
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]);
521 /* Create a byte-swapped copy of the ring and write it to
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());
531 /** Ring buffer header in host byte order */
533 /** Elements in ring in host byte order */
537 // Remove default constructor
540 /** Guest physical memory proxy */
542 /** Guest physical base address of the ring buffer */
546 /** Ring of available (incoming) descriptors */
547 VirtRing<VirtDescriptor::Index> avail;
548 /** Ring of used (outgoing) descriptors */
549 VirtRing<struct vring_used_elem> used;
551 /** Offset of last consumed descriptor in the VirtQueue::avail
553 uint16_t _last_avail;
555 /** Vector of pre-created descriptors indexed by their index into
557 std::vector<VirtDescriptor> descriptors;
561 * Base class for all VirtIO-based devices.
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.
567 * @see https://github.com/rustyrussell/virtio-spec
568 * @see http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html
570 class VirtIODeviceBase : public SimObject
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
580 typedef uint16_t VirtAddress;
581 /** Device Type (sometimes known as subsystem ID) */
582 typedef uint16_t DeviceId;
584 BitUnion8(DeviceStatus)
586 Bitfield<2> driver_ok;
588 Bitfield<0> acknowledge;
589 EndBitUnion(DeviceStatus)
591 typedef VirtIODeviceBaseParams Params;
592 VirtIODeviceBase(Params *params, DeviceId id, size_t config_size,
593 FeatureBits features);
594 virtual ~VirtIODeviceBase();
598 * @name SimObject Interfaces
600 void serialize(CheckpointOut &cp) const override;
601 void unserialize(CheckpointIn &cp) override;
607 * @name Device Model Interfaces
611 * Inform the guest of available buffers.
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.
622 transKick->process();
626 * Register a new VirtQueue with the device model.
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.
633 * @warning This method may only be called from the device model
636 void registerQueue(VirtQueue &queue);
640 * Feature set accepted by the guest.
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
649 FeatureBits guestFeatures;
654 * @name Optional VirtIO Interfaces
657 * Read from the configuration space of a device.
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.
664 * @warning The address in the packet should not be used to
665 * determine the offset into a device's configuration space.
667 * @param pkt Read request packet.
668 * @param cfgOffset Offset into the device's configuration space.
670 virtual void readConfig(PacketPtr pkt, Addr cfgOffset);
672 * Write to the configuration space of a device.
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.
679 * @warning The address in the packet should not be used to
680 * determine the offset into a device's configuration space.
682 * @param pkt Write request packet.
683 * @param cfgOffset Offset into the device's configuration space.
685 virtual void writeConfig(PacketPtr pkt, Addr cfgOffset);
688 * Driver-request device reset.
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.
696 * @note Always call the reset method of the base class from
697 * device-specific reset methods.
699 virtual void reset();
704 * @name Device Model Helpers
708 * Read configuration data from a device structure.
710 * @param pkt Read request packet.
711 * @param cfgOffset Offset into the device's configuration space.
712 * @param cfg Device configuration
714 void readConfigBlob(PacketPtr pkt, Addr cfgOffset, const uint8_t *cfg);
717 * Write configuration data to a device structure.
719 * @param pkt Write request packet.
720 * @param cfgOffset Offset into the device's configuration space.
721 * @param cfg Device configuration
723 void writeConfigBlob(PacketPtr pkt, Addr cfgOffset, uint8_t *cfg);
729 * @name VirtIO Transport Interfaces
732 * Register a callback to kick the guest through the transport
735 * @param c Callback into transport interface.
737 void registerKickCallback(Callback *c) {
744 * Driver is requesting service.
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.
750 * @param index ID of the queue with pending actions.
752 void onNotify(QueueID index);
756 * Change currently active queue.
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.
762 * @param idx ID of the queue to select.
764 void setQueueSelect(QueueID idx) { _queueSelect = idx; }
766 * Get the currently active queue.
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.
772 * @return The ID of the currently active queue.
774 QueueID getQueueSelect() const { return _queueSelect; }
777 * Change the host physical address of the currently active queue.
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
784 * @see setQueueSelect
785 * @see getQueueSelect
787 * @param address New address of the currently active queue (in
790 void setQueueAddress(uint32_t address);
792 * Get the host physical address of the currently active queue.
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
799 * @see setQueueSelect
800 * @see getQueueSelect
802 * @return Address of the currently active queue (in pages).
804 uint32_t getQueueAddress() const;
807 * Get the size (descriptors) of the currently active queue.
809 * @return Size of the currently active queue in number of
812 uint16_t getQueueSize() const { return getCurrentQueue().getSize(); }
815 * Update device status and optionally reset device.
817 * The special device status of 0 is used to reset the device by
820 * @param status New device status.
822 void setDeviceStatus(DeviceStatus status);
825 * Retrieve the device status.
827 * @return Device status.
829 DeviceStatus getDeviceStatus() const { return _deviceStatus; }
832 * Set feature bits accepted by the guest driver.
834 * This enables a subset of the features offered by the device
835 * model through the getGuestFeatures() interface.
837 void setGuestFeatures(FeatureBits features);
840 * Get features accepted by the guest driver.
842 * @return Currently active features.
844 FeatureBits getGuestFeatures() const { return guestFeatures; }
846 /** Device ID (sometimes known as subsystem ID) */
847 const DeviceId deviceId;
849 /** Size of the device's configuration space */
850 const size_t configSize;
852 /** Feature set offered by the device */
853 const FeatureBits deviceFeatures;
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();
863 * Status of the device
865 * @see getDeviceStatus
866 * @see setDeviceStatus
868 DeviceStatus _deviceStatus;
870 /** Queue select register (set by guest) */
871 QueueID _queueSelect;
873 /** List of virtual queues supported by this device */
874 std::vector<VirtQueue *> _queues;
876 /** Callbacks to kick the guest through the transport layer */
880 class VirtIODummyDevice : public VirtIODeviceBase
883 VirtIODummyDevice(VirtIODummyDeviceParams *params);
886 /** VirtIO device ID */
887 static const DeviceId ID_INVALID = 0x00;
890 #endif // __DEV_VIRTIO_BASE_HH__