PCIDriverKit ドライバー (DEXT) からユーザー空間アプリケーションに PCI Base Address Register (BAR) をメモリーマップする方法は?
ドライバー拡張機能からアプリケーションへのメモリ マッピングは、ユーザー クライアント サブクラス (ドライバー側) でIOUserClient::CopyClientMemoryForTypeを実装し、 IOConnectMapMemory64を(ユーザー空間アプリケーション側から) 呼び出すことによって実現できます。これは、この関連する回答で非常にうまく完全に説明されています。
唯一欠けているビットは、目的の PCI BAR に対応するIOMemoryDescriptorCopyClientMemoryForType
を取得して、それを実装から返すことです。
サンプルコード
別の言い方をすると、次の単純化されたコードが与えられた場合、 の実装は何になるでしょうimaginaryFunctionWhichReturnsTheBARBuffer
か?
kern_return_t IMPL(MyUserClient, CopyClientMemoryForType) //(uint64_t type, uint64_t *options, IOMemoryDescriptor **memory)
{
IOMemoryDescriptor* buffer = nullptr;
imaginaryFunctionWhichReturnsTheBARBuffer(ivars->pciDevice /* IOPCIDevice */, kPCIMemoryRangeBAR0, &buffer);
*memory = buffer;
return kIOReturnSuccess;
}
前のコードivars->pciDevice
では、すぐに使用できるIOPCIDeviceを参照しています (例:最新のベスト プラクティスに従って、正常に一致し、開かれ、構成されています)。
これは、さまざまな構成およびメモリの読み取り/書き込み方法を使用して、目的の PCI BAR メモリから明示的なオフセットにアクセスすることが既に可能であることを意味します。欠けている (または不明な) のは、これらの API (または同等の API) を使用して、PCI BARに対応するバッファー全体をユーザー空間アプリケーションにマップする方法です。
関連するかどうかわからないランダムなメモ
関連する質問からのこの回答: DriverKit システム拡張機能にメモリを割り当て、それを別のプロセスにマップする方法は? 次の引用が含まれています。
[...] 返されるメモリ記述子は、例で使用したように IOBufferMemoryDescriptor である必要はありません。PCI BAR などでもかまいません。
これはまさに私がやりたいことなので、少なくとも可能であるように思えます。唯一残っている問題は、それをどのように実装するかです。
同様の質問が Apple フォーラムに投稿されており、(この記事の執筆時点では) まだ回答が得られていませんが、役立つヒントがいくつか含まれています。
次のシグネチャを持つ PCIDriverKit にプライベート関数があるようです。
virtual kern_return_t IOPCIDevice::_CopyDeviceMemoryWithIndex(uint64_t memoryIndex, IOMemoryDescriptor** memory, IOService* forClient)
(文書化されていないため) 正確に何をすべきかを判断するのは困難ですが、署名は私が探している機能と一致しているようです。ただし、これを使用しようとすると、常にエラー コードが返されます (元のフォーラム投稿で報告されたものと同様です)。として渡される引数によってエラーコードが異なるようです
IOService *forClient
)。その投稿のもう 1 つの良い点は、必要なことを達成するために使用できるカーネル拡張機能 (KEXT) で使用できるgetDeviceMemoryWithIndexがあることです (ドライバーが PCI カーネル拡張機能として実装されている場合、これは現在非推奨になっているようです)。
ただし、この機能はドライバー拡張機能 (DEXT) では使用できないようです。したがって、この質問を構成する別の質問は次のようになります:
getDeviceMemoryWithIndex
PCIDriverKit ドライバー拡張機能に相当するものは何ですか?