base.hh revision 11168:f98eb2da15a4
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 : public Serializable { 316public: 317 virtual ~VirtQueue() {}; 318 319 /** @{ 320 * @name Checkpointing Interface 321 */ 322 void serialize(CheckpointOut &cp) const override; 323 void unserialize(CheckpointIn &cp) override; 324 325 /** @{ 326 * @name Low-level Device Interface 327 */ 328 /** 329 * Set the base address of this queue. 330 * 331 * @param address Guest physical base address of the queue. 332 */ 333 void setAddress(Addr address); 334 /** 335 * Get the guest physical address of this queue. 336 * 337 * @return Physical address in guest where this queue resides. 338 */ 339 Addr getAddress() const { return _address; } 340 341 /** 342 * Get the number of descriptors available in this queue. 343 * 344 * @return Size of queue in descriptors. 345 */ 346 uint16_t getSize() const { return _size; } 347 348 /** 349 * Get a pointer to a specific descriptor in the queue. 350 * 351 * @note This interfaces is normally only used by VirtDescriptor 352 * to follow descriptor chains. Device models typically don't need 353 * to use it. 354 * 355 * @return Pointer to a VirtDescriptor. 356 */ 357 VirtDescriptor *getDescriptor(VirtDescriptor::Index index) { 358 return &descriptors[index]; 359 } 360 /** @} */ 361 362 /** @{ 363 * @name Device Model Interfaces 364 */ 365 /** 366 * Get an incoming descriptor chain from the queue. 367 * 368 * @return Pointer to descriptor on success, NULL if no pending 369 * descriptors are available. 370 */ 371 VirtDescriptor *consumeDescriptor(); 372 /** 373 * Send a descriptor chain to the guest. 374 * 375 * This method posts a descriptor chain to the guest after a 376 * device model has finished processing it. The device model 377 * typically needs to call VirtIODeviceBase::kick() to deliver 378 * notify tell the guest that the queue has been updated. 379 * 380 * @note The desc parameter must refer to the first descriptor in 381 * a chain that has been retrieved using consumeDescriptor(). 382 * 383 * @note The len parameter specified the amount of data produced 384 * by the device model. It seems to be ignored by Linux and it is 385 * not well defined. 386 * 387 * @param desc Start of descriptor chain. 388 * @param len Length of the produced data. 389 */ 390 void produceDescriptor(VirtDescriptor *desc, uint32_t len); 391 /** @} */ 392 393 /** @{ 394 * @name Device Model Callbacks 395 */ 396 /** 397 * Notify queue of pending events. 398 * 399 * This method is called by VirtIODeviceBase::onNotify() to notify 400 * the device model of pending data in a virtqueue. The default 401 * implementation of this method iterates over the available 402 * descriptor chains and calls onNotifyDescriptor() for every new 403 * incoming chain. 404 * 405 * Device models should normally overload one of onNotify() and 406 * onNotifyDescriptor(). 407 */ 408 virtual void onNotify(); 409 /** 410 * Notify queue of pending incoming descriptor. 411 * 412 * This method is called by the default implementation of 413 * onNotify() to notify the device model of pending data in a 414 * descriptor chain. 415 * 416 * Device models should normally overload one of onNotify() and 417 * onNotifyDescriptor(). 418 */ 419 virtual void onNotifyDescriptor(VirtDescriptor *desc) {}; 420 /** @} */ 421 422 /** @{ 423 * @name Debug interfaces 424 */ 425 /** Dump the contents of a queue */ 426 void dump() const; 427 /** @} */ 428 429 /** @{ */ 430 /** 431 * Page size used by VirtIO.\ It's hard-coded to 4096 bytes in 432 * the spec for historical reasons. 433 */ 434 static const unsigned ALIGN_BITS = 12; 435 static const unsigned ALIGN_SIZE = 1 << ALIGN_BITS; 436 /** @} */ 437 438 protected: 439 /** 440 * Instantiate a new virtqueue. 441 * 442 * Instantiate a virtqueue with a fixed size. The size is 443 * specified in descriptors which are defined as 4096 bytes each. 444 * 445 * @param proxy Proxy to the guest physical memory. 446 * @param size Size in descriptors/pages. 447 */ 448 VirtQueue(PortProxy &proxy, uint16_t size); 449 450 private: 451 VirtQueue(); 452 453 /** Queue size in terms of number of descriptors */ 454 const uint16_t _size; 455 /** Base address of the queue */ 456 Addr _address; 457 /** Guest physical memory proxy */ 458 PortProxy &memProxy; 459 460 private: 461 /** 462 * VirtIO ring buffer wrapper. 463 * 464 * This class wraps a VirtIO ring buffer. The template parameter T 465 * is used to select the data type for the items in the ring (used 466 * or available descriptors). 467 */ 468 template<typename T> 469 class VirtRing 470 { 471 public: 472 typedef uint16_t Flags; 473 typedef uint16_t Index; 474 475 struct Header { 476 Flags flags; 477 Index index; 478 } M5_ATTR_PACKED; 479 480 VirtRing<T>(PortProxy &proxy, uint16_t size) 481 : header{0, 0}, ring(size), _proxy(proxy), _base(0) {} 482 483 /** 484 * Set the base address of the VirtIO ring buffer. 485 * 486 * @param addr New host physical address 487 */ 488 void setAddress(Addr addr) { _base = addr; } 489 490 /** Update the ring buffer header with data from the guest. */ 491 void readHeader() { 492 assert(_base != 0); 493 _proxy.readBlob(_base, (uint8_t *)&header, sizeof(header)); 494 header.flags = vtoh_legacy(header.flags); 495 header.index = vtoh_legacy(header.index); 496 } 497 498 void writeHeader() { 499 Header out; 500 assert(_base != 0); 501 out.flags = htov_legacy(header.flags); 502 out.index = htov_legacy(header.index); 503 _proxy.writeBlob(_base, (uint8_t *)&out, sizeof(out)); 504 } 505 506 void read() { 507 readHeader(); 508 509 /* Read and byte-swap the elements in the ring */ 510 T temp[ring.size()]; 511 _proxy.readBlob(_base + sizeof(header), 512 (uint8_t *)temp, sizeof(T) * ring.size()); 513 for (int i = 0; i < ring.size(); ++i) 514 ring[i] = vtoh_legacy(temp[i]); 515 } 516 517 void write() { 518 assert(_base != 0); 519 /* Create a byte-swapped copy of the ring and write it to 520 * guest memory. */ 521 T temp[ring.size()]; 522 for (int i = 0; i < ring.size(); ++i) 523 temp[i] = htov_legacy(ring[i]); 524 _proxy.writeBlob(_base + sizeof(header), 525 (uint8_t *)temp, sizeof(T) * ring.size()); 526 writeHeader(); 527 } 528 529 /** Ring buffer header in host byte order */ 530 Header header; 531 /** Elements in ring in host byte order */ 532 std::vector<T> ring; 533 534 private: 535 // Remove default constructor 536 VirtRing<T>(); 537 538 /** Guest physical memory proxy */ 539 PortProxy &_proxy; 540 /** Guest physical base address of the ring buffer */ 541 Addr _base; 542 }; 543 544 /** Ring of available (incoming) descriptors */ 545 VirtRing<VirtDescriptor::Index> avail; 546 /** Ring of used (outgoing) descriptors */ 547 VirtRing<struct vring_used_elem> used; 548 549 /** Offset of last consumed descriptor in the VirtQueue::avail 550 * ring */ 551 uint16_t _last_avail; 552 553 /** Vector of pre-created descriptors indexed by their index into 554 * the queue. */ 555 std::vector<VirtDescriptor> descriptors; 556}; 557 558/** 559 * Base class for all VirtIO-based devices. 560 * 561 * This class implements the functionality of the VirtIO 0.9.5 562 * specification. This version of VirtIO is also known as "legacy" in 563 * the VirtIO 1.0 specification from OASIS. 564 * 565 * @see https://github.com/rustyrussell/virtio-spec 566 * @see http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html 567 */ 568class VirtIODeviceBase : public SimObject 569{ 570 public: 571 typedef uint16_t QueueID; 572 typedef uint32_t FeatureBits; 573 /** This is a VirtQueue address as exposed through the low-level 574 * interface.\ The address needs to be multiplied by the page size 575 * (seems to be hardcoded to 4096 in the spec) to get the real 576 * physical address. 577 */ 578 typedef uint16_t VirtAddress; 579 /** Device Type (sometimes known as subsystem ID) */ 580 typedef uint16_t DeviceId; 581 582 BitUnion8(DeviceStatus) 583 Bitfield<7> failed; 584 Bitfield<2> driver_ok; 585 Bitfield<1> driver; 586 Bitfield<0> acknowledge; 587 EndBitUnion(DeviceStatus) 588 589 typedef VirtIODeviceBaseParams Params; 590 VirtIODeviceBase(Params *params, DeviceId id, size_t config_size, 591 FeatureBits features); 592 virtual ~VirtIODeviceBase(); 593 594 public: 595 /** @{ 596 * @name SimObject Interfaces 597 */ 598 void serialize(CheckpointOut &cp) const override; 599 void unserialize(CheckpointIn &cp) override; 600 /** @} */ 601 602 603 protected: 604 /** @{ 605 * @name Device Model Interfaces 606 */ 607 608 /** 609 * Inform the guest of available buffers. 610 * 611 * When a device model has finished processing incoming buffers 612 * (after onNotify has been called), it typically needs to inform 613 * the guest that there are new pending outgoing buffers. The 614 * method used to inform the guest is transport dependent, but is 615 * typically through an interrupt. Device models call this method 616 * to tell the transport interface to notify the guest. 617 */ 618 void kick() { 619 assert(transKick); 620 transKick->process(); 621 }; 622 623 /** 624 * Register a new VirtQueue with the device model. 625 * 626 * Devices typically register at least one VirtQueue to use for 627 * communication with the guest. This <i>must</i> be done from the 628 * constructor since the number of queues are assumed to be 629 * constant throughout the lifetime of the device. 630 * 631 * @warning This method may only be called from the device model 632 * constructor. 633 */ 634 void registerQueue(VirtQueue &queue); 635 636 637 /** 638 * Feature set accepted by the guest. 639 * 640 * When the guest starts the driver for the device, it starts by 641 * negotiating features. The device first offers a set of features 642 * (see deviceFeatures), the driver then notifies the device of 643 * which features it accepted. The base class will automatically 644 * accept any feature set that is a subset of the features offered 645 * by the device. 646 */ 647 FeatureBits guestFeatures; 648 /** @} */ 649 650 public: 651 /** @{ 652 * @name Optional VirtIO Interfaces 653 */ 654 /** 655 * Read from the configuration space of a device. 656 * 657 * This method is called by the transport interface to read data 658 * from a device model's configuration space. The device model 659 * should use the cfgOffset parameter as the offset into its 660 * configuration space. 661 * 662 * @warning The address in the packet should not be used to 663 * determine the offset into a device's configuration space. 664 * 665 * @param pkt Read request packet. 666 * @param cfgOffset Offset into the device's configuration space. 667 */ 668 virtual void readConfig(PacketPtr pkt, Addr cfgOffset); 669 /** 670 * Write to the configuration space of a device. 671 * 672 * This method is called by the transport interface to write data 673 * into a device model's configuration space. The device model 674 * should use the cfgOffset parameter as the offset into its 675 * configuration space. 676 * 677 * @warning The address in the packet should not be used to 678 * determine the offset into a device's configuration space. 679 * 680 * @param pkt Write request packet. 681 * @param cfgOffset Offset into the device's configuration space. 682 */ 683 virtual void writeConfig(PacketPtr pkt, Addr cfgOffset); 684 685 /** 686 * Driver-request device reset. 687 * 688 * The device driver may reset a device by writing zero to the 689 * device status register (using setDeviceStatus()), which causes 690 * this method to be called. Device models overriding this method 691 * <i>must</i> ensure that the reset method of the base class is 692 * called when the device is reset. 693 * 694 * @note Always call the reset method of the base class from 695 * device-specific reset methods. 696 */ 697 virtual void reset(); 698 /** @} */ 699 700 protected: 701 /** @{ 702 * @name Device Model Helpers 703 */ 704 705 /** 706 * Read configuration data from a device structure. 707 * 708 * @param pkt Read request packet. 709 * @param cfgOffset Offset into the device's configuration space. 710 * @param cfg Device configuration 711 */ 712 void readConfigBlob(PacketPtr pkt, Addr cfgOffset, const uint8_t *cfg); 713 714 /** 715 * Write configuration data to a device structure. 716 * 717 * @param pkt Write request packet. 718 * @param cfgOffset Offset into the device's configuration space. 719 * @param cfg Device configuration 720 */ 721 void writeConfigBlob(PacketPtr pkt, Addr cfgOffset, uint8_t *cfg); 722 723 /** @} */ 724 725 public: 726 /** @{ 727 * @name VirtIO Transport Interfaces 728 */ 729 /** 730 * Register a callback to kick the guest through the transport 731 * interface. 732 * 733 * @param c Callback into transport interface. 734 */ 735 void registerKickCallback(Callback *c) { 736 assert(!transKick); 737 transKick = c; 738 } 739 740 741 /** 742 * Driver is requesting service. 743 * 744 * This method is called by the underlying hardware interface 745 * (e.g., PciVirtIO or MmmioVirtIO) to notify a device of pending 746 * incoming descriptors. 747 * 748 * @param index ID of the queue with pending actions. 749 */ 750 void onNotify(QueueID index); 751 752 753 /** 754 * Change currently active queue. 755 * 756 * The transport interface works on a queue at a time. The 757 * currently active queue is decided by the value of the queue 758 * select field in a device. 759 * 760 * @param idx ID of the queue to select. 761 */ 762 void setQueueSelect(QueueID idx) { _queueSelect = idx; } 763 /** 764 * Get the currently active queue. 765 * 766 * The transport interface works on a queue at a time. The 767 * currently active queue is decided by the value of the queue 768 * select field in a device. 769 * 770 * @return The ID of the currently active queue. 771 */ 772 QueueID getQueueSelect() const { return _queueSelect; } 773 774 /** 775 * Change the host physical address of the currently active queue. 776 * 777 * @note The new address is specified in multiples of the page 778 * size (fixed to 4096 bytes in the standard). For example, if the 779 * address 10 is selected, the actual host physical address will 780 * be 40960. 781 * 782 * @see setQueueSelect 783 * @see getQueueSelect 784 * 785 * @param address New address of the currently active queue (in 786 * pages). 787 */ 788 void setQueueAddress(uint32_t address); 789 /** 790 * Get the host physical address of the currently active queue. 791 * 792 * @note The new address is specified in multiples of the page 793 * size (fixed to 4096 bytes in the standard). For example, if the 794 * address 10 is selected, the actual host physical address will 795 * be 40960. 796 * 797 * @see setQueueSelect 798 * @see getQueueSelect 799 * 800 * @return Address of the currently active queue (in pages). 801 */ 802 uint32_t getQueueAddress() const; 803 804 /** 805 * Get the size (descriptors) of the currently active queue. 806 * 807 * @return Size of the currently active queue in number of 808 * descriptors. 809 */ 810 uint16_t getQueueSize() const { return getCurrentQueue().getSize(); } 811 812 /** 813 * Update device status and optionally reset device. 814 * 815 * The special device status of 0 is used to reset the device by 816 * calling reset(). 817 * 818 * @param status New device status. 819 */ 820 void setDeviceStatus(DeviceStatus status); 821 822 /** 823 * Retrieve the device status. 824 * 825 * @return Device status. 826 */ 827 DeviceStatus getDeviceStatus() const { return _deviceStatus; } 828 829 /** 830 * Set feature bits accepted by the guest driver. 831 * 832 * This enables a subset of the features offered by the device 833 * model through the getGuestFeatures() interface. 834 */ 835 void setGuestFeatures(FeatureBits features); 836 837 /** 838 * Get features accepted by the guest driver. 839 * 840 * @return Currently active features. 841 */ 842 FeatureBits getGuestFeatures() const { return guestFeatures; } 843 844 /** Device ID (sometimes known as subsystem ID) */ 845 const DeviceId deviceId; 846 847 /** Size of the device's configuration space */ 848 const size_t configSize; 849 850 /** Feature set offered by the device */ 851 const FeatureBits deviceFeatures; 852 /** @} */ 853 854 private: 855 /** Convenience method to get the currently selected queue */ 856 const VirtQueue &getCurrentQueue() const; 857 /** Convenience method to get the currently selected queue */ 858 VirtQueue &getCurrentQueue(); 859 860 /** 861 * Status of the device 862 * 863 * @see getDeviceStatus 864 * @see setDeviceStatus 865 */ 866 DeviceStatus _deviceStatus; 867 868 /** Queue select register (set by guest) */ 869 QueueID _queueSelect; 870 871 /** List of virtual queues supported by this device */ 872 std::vector<VirtQueue *> _queues; 873 874 /** Callbacks to kick the guest through the transport layer */ 875 Callback *transKick; 876}; 877 878#endif // __DEV_VIRTIO_BASE_HH__ 879