|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.