Annotation of nono/vm/virtio_base.h, revision 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.