--- nono/vm/virtio_base.h 2026/04/29 17:05:32 1.1.1.3 +++ nono/vm/virtio_base.h 2026/04/29 17:05:41 1.1.1.4 @@ -12,6 +12,7 @@ #include "device.h" #include "message.h" +#include "mybswap.h" #include "thread.h" #include #include @@ -66,11 +67,10 @@ class VirtIOSeg { public: uint32 addr {}; // セグメントアドレス (ゲストアドレス) - uint32 pos {}; // このセグメントのチェイン先頭からの位置 uint32 len {}; // このセグメント長 - VirtIOSeg(uint32 addr_, uint32 pos_, uint32 len_) - : addr(addr_), pos(pos_), len(len_) + VirtIOSeg(uint32 addr_, uint32 len_) + : addr(addr_), len(len_) { } }; @@ -78,18 +78,46 @@ class VirtIOSeg // ディスクリプタチェイン。 // ファイルハンドルのようなものも兼ねている。 // 元の仕様からシーケンシャルアクセスを想定しているようなので、ここでも -// シーケンシャルアクセスを前提とする。そのため pos が UsedRing に書き込む +// シーケンシャルアクセスを前提とする。そのため pos() が UsedRing に書き込む // バイト数になる。 class VirtIOReq { public: VirtQueue *q {}; uint32 idx {}; // このディスクリプタチェインの先頭インデックス - uint32 len {}; // このディスクリプタチェインの総バイト数 - uint32 pos {}; // 現在位置 (Used としても使用する) - std::vector buf {}; // バッファセグメント - int curseg {}; // 現在のセグメント (buf[] のインデックス) + int rseg {}; // 現在の読み込みセグメントインデックス + uint32 roff {}; // 読み込み位置(セグメント内の相対位置) + std::vector rbuf {}; // 読み込み用セグメント + uint32 rlen {}; // 読み込みセグメントの総バイト数 + + int wseg {}; // 現在の書き込みセグメントインデックス + uint32 woff {}; // 書き込み位置(セグメント内の相対位置) + std::vector wbuf {}; // 書き込み用セグメント + uint32 wlen {}; // 書き込みセグメントの総バイト数 + + // このディスクリプタチェインの総バイト数。 + uint32 totallen() const noexcept { return rlen + wlen; } + + // 読み込みセグメントの残りバイト数。 + uint32 rremain() const { return rlen - rpos(); } + + // 読み込みセグメントの残りをすべて読み捨てる。 + void rskip() { + rseg = rbuf.size(); + roff = 0; + } + + // 読み込みセグメントの先頭からの現在位置を返す。 + uint32 rpos() const; + // 書き込みセグメントの先頭からの現在位置を返す。 + uint32 wpos() const; + // 処理した総バイト数を返す。 + uint32 pos() const { return rpos() + wpos(); } + + // 読み込みまたは書き込みが末尾に到達していれば true を返す。 + bool reof() const { return rseg >= rbuf.size(); } + bool weof() const { return wseg >= wbuf.size(); } }; // VirtIO 基本クラス @@ -146,9 +174,15 @@ class VirtIODevice : public IODevice uint32 ReqReadU8(VirtIOReq&); uint32 ReqReadLE16(VirtIOReq&); uint64 ReqReadLE32(VirtIOReq&); + uint32 ReqReadBE16(VirtIOReq& req) { return bswap16(ReqReadLE16(req)); } + uint32 ReqReadBE32(VirtIOReq& req) { return bswap32(ReqReadLE32(req)); } bool ReqReadLE32(VirtIOReq&, uint32 *); bool ReqReadLE64(VirtIOReq&, uint64 *); bool ReqWriteU8(VirtIOReq&, uint32 data); + bool ReqWriteLE16(VirtIOReq&, uint32 data); + bool ReqWriteLE32(VirtIOReq&, uint32 data); + uint32 ReqReadRegion(VirtIOReq&, uint8 *dst, uint32 dstlen); + uint32 ReqWriteRegion(VirtIOReq&, const uint8 *src, uint32 srclen); // 裏スレッドからの処理完了メッセージ void DoneMessage(MessageID, uint32);