|
|
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.