Annotation of nono/vm/virtio_base.h, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2024 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // VirtIO
                      9: //
                     10: 
                     11: #pragma once
                     12: 
                     13: #include "device.h"
                     14: #include "message.h"
                     15: #include "thread.h"
                     16: #include <array>
                     17: #include <condition_variable>
                     18: 
                     19: class InterruptDevice;
                     20: class MainbusDevice;
                     21: class TextScreen;
                     22: class VirtIOThread;
                     23: class VirtQDesc;
                     24: 
                     25: class VirtQueue
                     26: {
                     27:  public:
                     28:        VirtQueue(int idx_, const std::string& name_, int num_max_);
                     29: 
                     30:        uint32 last_avail_idx {};
                     31: 
                     32:        int idx {};                             // 自身が何番目か
                     33:        std::string name {};    // キュー名(仕様から決まる)
                     34: 
                     35:        uint32 desc {};                 // QUEUE_DESC (下位32ビットのみ)
                     36:        uint32 driver {};               // QUEUE_DRIVER (下位32ビットのみ)
                     37:        uint32 device {};               // QUEUE_DEVICE (下位32ビットのみ)
                     38: 
                     39:        int num {};                             // QUEUE_NUM (合意できたディスクリプタ数)
                     40:        int num_max {};                 // QUEUE_NUM の上限
                     41:        uint32 ready {};                // QUEUE_READY
                     42: };
                     43: 
                     44: class VirtIOSeg
                     45: {
                     46:  public:
                     47:        uint32 addr {};                 // バッファアドレス (ゲストアドレス)
                     48:        uint32 len {};                  // バッファ長
                     49: 
                     50:        VirtIOSeg(uint32 addr_, uint32 len_)
                     51:                : addr(addr_), len(len_)
                     52:        {
                     53:        }
                     54: };
                     55: 
                     56: // ディスクリプタチェインの基本クラス
                     57: class VirtIOReq
                     58: {
                     59:  public:
                     60:        VirtQueue *q {};
                     61:        uint32 idx {};                  // このディスクリプタチェインの先頭インデックス
                     62:        uint32 len {};                  // このディスクリプタチェインの総バイト数
                     63:        std::vector<VirtIOSeg> buf {};  // バッファセグメント
                     64: 
                     65:        int curseg {};                  // 書き込み位置、現在のセグメント
                     66:        int offset {};                  // 書き込み位置、セグメント内のオフセット
                     67: };
                     68: 
                     69: // VirtIO 基本クラス
                     70: class VirtIODevice : public IODevice
                     71: {
                     72:        using inherited = IODevice;
                     73: 
                     74:  protected:
                     75:        // 仕様書には名前が出てこないけど上限
                     76:        static const uint MAX_FEATURES_SEL = 2;
                     77: 
                     78:        // モニタ幅
                     79:        static const int MONITOR_WIDTH = 75;
                     80: 
                     81:        // 動作には不要だがモニタに表示したいので…。
                     82:        static const uint32 baseaddr = 0xff070000;
                     83: 
                     84:  public:
                     85:        VirtIODevice(int objid_, int slot_);
                     86:        ~VirtIODevice() override;
                     87: 
                     88:        bool Create() override;
                     89:        void SetLogLevel(int loglevel_) override;
                     90:        bool Init() override;
                     91:        void ResetHard(bool poweron) override;
                     92: 
                     93:        busdata Read8(uint32 addr) override;
                     94:        busdata Read16(uint32 addr) override;
                     95:        busdata Read32(uint32 addr) override;
                     96:        busdata Write8(uint32 addr, uint32 data) override;
                     97:        busdata Write16(uint32 addr, uint32 data) override;
                     98:        busdata Write32(uint32 addr, uint32 data) override;
                     99:        busdata Peek8(uint32 addr) override;
                    100: 
                    101:        // QUEUE_NOTIFY の処理 (裏スレッドから呼ばれる)
                    102:        void QueueNotify(int idx);
                    103: 
                    104:  protected:
                    105:        int MonitorUpdateDev(TextScreen&, int y) const;
                    106:        int MonitorUpdateVirtQueue(TextScreen&, int y, const VirtQueue&) const;
                    107:        int MonitorUpdateVirtQDesc(TextScreen&, int y, const VirtQueue&) const;
                    108:        virtual uint32 GetReg(uint32 addr) const;
                    109:        virtual void QueueReady();
                    110: 
                    111:        // ディスクリプタを一つ処理する。
                    112:        virtual void ProcessDesc(VirtQueue *) = 0;
                    113: 
                    114:        // ディスクリプタを更新する。
                    115:        void CommitDesc(VirtQueue *, uint32 idx, uint32 len);
                    116: 
                    117:        // 裏スレッドからの処理完了メッセージ
                    118:        void DoneMessage(MessageID, uint32);
                    119:        // 処理完了
                    120:        void Done(VirtQueue *);
                    121: 
                    122:        void ChangeInterrupt();
                    123: 
                    124:        // メインバスアクセス
                    125:        uint32 ReadU8(uint32 addr);
                    126:        uint32 ReadLE16(uint32 addr);
                    127:        uint32 ReadLE32(uint32 addr);
                    128:        uint64 ReadLE64(uint32 addr);
                    129:        void WriteU8(uint32 addr, uint32 data);
                    130:        void WriteLE16(uint32 addr, uint32 data);
                    131:        void WriteLE32(uint32 addr, uint32 data);
                    132:        void WriteLE64(uint32 addr, uint64 data);
                    133:        uint32 PeekLE16(uint32 addr) const;
                    134:        uint32 PeekLE32(uint32 addr) const;
                    135: 
                    136:        uint32 ReadDesc(const VirtQueue *, VirtQDesc *desc, uint32 idx);
                    137:        void AddDataSegment(VirtIOReq *, uint32 addr, uint32 len, const char *);
                    138:        bool ReqAppendByte(VirtIOReq *, uint32 data);
                    139: 
                    140:        // DEVICE_FEATURES の feature 番目のビットを立てる。初期化用。
                    141:        void SetDeviceFeatures(int feature);
                    142:        // DEVICE_FEATURES の feature 番目の名前を返す。
                    143:        virtual const char *GetFeatureName(int feature) const;
                    144: 
                    145:        // DRIVER_FEATURES の feature 番目のビットが立っていれば true。
                    146:        bool GetDriverFeatures(int feature) const;
                    147: 
                    148:        int slot {};                            // VirtIO のスロット番号 (0-127)
                    149: 
                    150:        uint32 device_id {};            // DEVICE_ID
                    151:        uint32 vendor_id {};            // VENDOR_ID
                    152:        uint32 device_status {};        // STATUS
                    153: 
                    154:        uint32 device_sel {};           // DEVICE_FEATURES_SEL
                    155:        uint32 driver_sel {};           // DRIVER_FEATURES_SEL
                    156:        std::array<uint32, 2> device_features {};       // DEVICE_FEATURES
                    157:        std::array<uint32, 2> driver_features {};       // DRIVER_FEATURES
                    158: 
                    159:        uint32 queue_num {};            // QUEUE_NUM
                    160: 
                    161:        // VirtQueue。継承先で個数が決まっている。
                    162:        std::vector<VirtQueue> vqueues {};
                    163:        // QUEUE_SEL の値。
                    164:        uint32 queue_sel {};
                    165:        // QUEUE_SEL で選択されている現在の VirtQueue。選択されてなければ NULL。
                    166:        VirtQueue *vq {};
                    167: 
                    168:        uint32 intr_status {};                  // INTERRUPT_STATUS
                    169: 
                    170:        // 0x100 以降の領域
                    171:        std::array<uint8, 0x100> device_config {};
                    172: 
                    173:        char intrname[10] {};                   // 割り込み名
                    174: 
                    175:        MessageID msgid {};                             // 完了通知のメッセージ ID
                    176: 
                    177:        std::unique_ptr<VirtIOThread> backend /*{}*/;
                    178: 
                    179:        InterruptDevice *interrupt {};
                    180:        MainbusDevice *mainbus {};
                    181: };
                    182: 
                    183: // VirtIO 空きスロット用
                    184: class VirtIONoneDevice : public IODevice
                    185: {
                    186:        using inherited = IODevice;
                    187:  public:
                    188:        VirtIONoneDevice();
                    189:        ~VirtIONoneDevice() override;
                    190: 
                    191:        busdata Read32(uint32 addr) override;
                    192:        busdata Write32(uint32 addr, uint32 data) override;
                    193:        busdata Peek8(uint32 addr) override;
                    194: };
                    195: 
                    196: // 裏スレッド
                    197: class VirtIOThread : public ThreadDevice
                    198: {
                    199:        using inherited = ThreadDevice;
                    200: 
                    201:  protected:
                    202:        // REQ_QUEUE はキュー1本に1ビットずつ割り当てているので現状最大31まで。
                    203:        static const uint32 REQ_TERMINATE       = 0x80000000;   // スレッド終了指示
                    204:        static constexpr uint32 REQ_QUEUE(int idx) {            // QUEUE_NOTIFY 指示
                    205:                return (1U << idx);
                    206:        }
                    207: 
                    208:  public:
                    209:        VirtIOThread(VirtIODevice *parent_);
                    210:        ~VirtIOThread() override;
                    211: 
                    212:        void Terminate() override;
                    213: 
                    214:        // ゲストからの QUEUE_NOTIFY 要求
                    215:        void RequestQueueNotify(int);
                    216: 
                    217:  private:
                    218:        void ThreadRun() override;
                    219: 
                    220:  protected:
                    221:        // リクエストフラグ
                    222:        uint32 request {};
                    223:        std::mutex mtx {};
                    224:        std::condition_variable cv {};
                    225: 
                    226:        VirtIODevice *parent {};
                    227: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.