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 50struct VirtIODeviceBaseParams; 51struct VirtIODummyDeviceParams; 52 53class 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. */ 69template <typename T> inline T 70vtoh_legacy(T v) { 71 return TheISA::gtoh(v); 72} 73 74/** Convert host endianness to legacy VirtIO endianness. */ 75template <typename T> inline T 76htov_legacy(T v) { 77 return TheISA::htog(v); 78} 79 80 81template <> inline vring_used_elem 82vtoh_legacy(vring_used_elem v) { 83 v.id = vtoh_legacy(v.id); 84 v.len = vtoh_legacy(v.len); 85 return v; 86} 87 88template <> inline vring_used_elem 89htov_legacy(vring_used_elem v) { 90 v.id = htov_legacy(v.id); 91 v.len = htov_legacy(v.len); 92 return v; 93} 94 95template <> inline vring_desc 96vtoh_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 104template <> inline vring_desc 105htov_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 */ 136class 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 */ 317class VirtQueue : public Serializable { 318public: 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, &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, &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 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 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 */ 570class 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 880class 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__ 891