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