JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
デバイスドライバの記述     Oracle Solaris 10 8/11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

パート I Solaris プラットフォーム用デバイスドライバの設計

1.  Solaris デバイスドライバの概要

2.  Solaris カーネルとデバイスツリー

3.  マルチスレッド

4.  プロパティー

5.  イベントの管理とタスクのキュー

6.  ドライバの自動設定

7.  デバイスアクセス: プログラム式入出力

8.  割り込みハンドラ

9.  ダイレクトメモリーアクセス (DMA)

10.  デバイスメモリーおよびカーネルメモリーのマッピング

11.  デバイスコンテキスト管理

12.  電源管理

13.  Solaris ドライバの強化

Sun 障害管理アーキテクチャーの入出力障害サービス

予測的自己修復とは

Solaris Fault Manager

診断、疑いリスト、フォルトイベント

応答エージェント

メッセージ ID と辞書ファイル

システムトポロジ

エラー処理

障害管理機能の宣言

障害管理リソースのクリーンアップ

障害管理機能ビットマスクの取得

エラーの報告

アクセス属性構造体

DMA 属性構造体

エラー状態の取得

エラーのクリア

エラーハンドラの登録

障害管理のデータおよび状態の構造体

障害の診断

標準リーフデバイス診断

特殊なデバイス診断

イベントレジストリ

用語集

関連資料

Solaris デバイスドライバの防御的プログラミング手法

別個のデバイスドライバインスタンスの使用

DDI アクセスハンドルの排他的使用

破壊されたデータの検出

デバイス管理データおよび制御データの破壊

受信データの破壊

DMA 遮断

問題のある割り込みの処理

プログラミングのその他の考慮事項

スレッドの対話

トップダウン要求の脅威

適応型戦略

ドライバ強化テストハーネス

障害投入

テストハーネスの設定

テストハーネスのインストール

テストハーネスの設定

ドライバのテスト

障害の作成

障害の投入

障害投入プロセス

テストハーネスの警告

スクリプトによるテストプロセスの自動化

自動テストプロセス

14.  階層化ドライバインタフェース (LDI)

パート II 特定の種類のデバイスドライバの設計

15.  文字デバイスのドライバ

16.  ブロックデバイスのドライバ

17.  SCSI ターゲットドライバ

18.  SCSI ホストバスアダプタドライバ

19.  ネットワークデバイスのドライバ

20.  USB ドライバ

パート III デバイスドライバの構築

21.  ドライバのコンパイル、ロード、パッケージ化、およびテスト

22.  デバイスドライバのデバッグ、テスト、およびチューニング

23.  推奨されるコーティング方法

パート IV 付録

A.  ハードウェアの概要

B.  Solaris DDI/DKI サービスの概要

C.  64 ビットデバイスドライバの準備

D.  コンソールフレームバッファードライバ

索引

ドライバ強化テストハーネス

ドライバ強化テストハーネスは、入出力障害サービスおよび防御的プログラミングの要件が正しく満たされていることをテストします。強化されたデバイスドライバは、潜在的なハードウェア障害に対する耐性を備えています。開発者は、デバイスドライバ開発プロセスの一環として、ドライバの回復性能をテストする必要があります。この種類のテストでは、広範囲の一般的なハードウェア障害を、制御された反復可能な方法でドライバが処理できることを確認します。ドライバ強化テストハーネスを使用すると、開発者はそのようなハードウェア障害をソフトウェアでシミュレートできます。

ドライバ強化テストハーネスは、Solaris デバイスのドライバ開発ツールです。このテストハーネスは、開発中のドライバがそのハードウェアにアクセスするときに、広範囲の擬似的なハードウェア障害を投入します。この節では、テストハーネスを構成し、エラー投入仕様 (errdef) を作成して、デバイスドライバのテストを実行する方法について説明します。

テストハーネスはドライバからの各種 DDI ルーチンの呼び出しを横取りし、あたかもハードウェアが原因であるかのように、呼び出しの結果を破壊します。ハーネスでは、特定のレジスタへのアクセスに対する破壊に加えて、よりランダムな種類の破壊も定義できます。

テストハーネスでは、指定されたワークロードの実行中に、すべてのレジスタアクセスのほか、ダイレクトメモリーアクセス (DMA) と割り込みの使用状況を追跡することにより、テストスクリプトを自動生成できます。生成されたスクリプトでは、そのワークロードが再実行されるのと並行して、アクセスのたびに一連の障害が投入されます。

ドライバのテスト担当者は、生成されたスクリプトから、重複しているテストケースを削除するようにしてください。

テストハーネスは、bofi という名前 (バス操作への障害投入を意味する) のデバイスドライバと、2 つのユーザーレベルユーティリティー th_define(1M) および th_manage(1M) として実装されています。

テストハーネスは次の作業を行います。

障害投入

ドライバ強化テストハーネスは、ドライバがハードウェアにアクセスするたびにそれを横取りし、必要に応じてアクセスを破壊します。この節では、ドライバの回復性能をテストする障害を作成するにあたり、理解しておくことが望ましい情報を提供します。

Solaris のデバイスは、デバイスツリー (devinfo ツリー) と呼ばれるツリー状構造の内部で管理されます。devinfo ツリーの各ノードには、システムに存在するデバイスの特定のインスタンスに関する情報が格納されます。各リーフノードはデバイスドライバに対応し、ほかのすべてのノードはネクサスノードと呼ばれます。通常は、1 つのネクサスが 1 つのバスを表します。バスノードはリーフドライバをバスへの依存性から切り離し、アーキテクチャー的に独立したドライバを生成できるようにします。

多くの DDI 関数、特にデータアクセス関数は、結果としてバスネクサスドライバへの上位呼び出しになります。リーフドライバはハードウェアにアクセスするとき、アクセスルーチンにハンドルを渡します。バスネクサスは、ハンドルを操作して要求に応じる方法を理解しています。DDI 準拠のドライバはこれらの DDI アクセスルーチンを使用してのみ、ハードウェアにアクセスします。テストハーネスは、指定されたバスネクサスにこれらの上位呼び出しが到達する前に横取りします。ドライバのテスト担当者が指定した基準にデータアクセスが一致すれば、アクセスは破壊されます。基準に一致しなかったデータアクセスは、バスネクサスに渡されて通常どおり処理されます。

ドライバは ddi_regs_map_setup(9F) 関数を使用してアクセスハンドルを取得します。

ddi_regs_map_setup(dip, rset, ma, offset, size, handle)

引数では、対応づけ対象の「オフボード」メモリーを指定します。ハンドルはドライバをバス階層構造の詳細から分離するためのものなので、対応づけされた入出力アドレスをドライバが参照するときは、返されたハンドルを使用する必要があります。したがって、返される対応づけされたアドレスである ma を直接使用しないでください。対応づけされたアドレスを直接使用すると、その時点以降、データアクセス関数の機構を使用しないことになります。

プログラム式入出力では、データアクセス関数の組み合わせは次のようになります。

X および repcnt は転送されるバイト数です。X はバス転送サイズ (8、16、32、または 64 バイト) です。

DMA にはこれに類似した、より充実したデータアクセス関数の集合が用意されています。

テストハーネスの設定

ドライバ強化テストハーネスは Solaris Developer Cluster に含まれています。この Solaris クラスタがインストールされていない場合、プラットフォームに適合したテストハーネスパッケージを手作業でインストールする必要があります。

テストハーネスのインストール

テストハーネスパッケージ (SUNWftduu および SUNWftdur) をインストールするには、pkgadd(1M) コマンドを使用します。

スーパーユーザーとして、パッケージが存在するディレクトリに移動し、次のように入力します。

# pkgadd -d . SUNWftduu SUNWftdur

テストハーネスの設定

テストハーネスをインストールしたら、/kernel/drv/bofi.conf ファイルのプロパティーを設定して、テストするドライバと対話するようにハーネスを設定します。ハーネスの設定が完了したら、システムを再起動してハーネスドライバをロードします。

テストハーネスの動作は、/kernel/drv/bofi.conf 設定ファイルで設定される起動時プロパティーによって制御されます。

ハーネスを最初にインストールするときに、次のプロパティーを設定して、テストするドライバへの DDI アクセスをハーネスが横取りするようにします。

bofi-nexus

バスのネクサスタイプ (例: PCI バス)

bofi-to-test

テストするドライバの名前

たとえば、xyznetdrv という名前の PCI バスネットワークドライバをテストするには、プロパティー値を次のように設定します。

bofi-nexus="pci"
bofi-to-test="xyznetdrv"

上記以外のプロパティーは、PIO を使用する周辺機器との間の読み書きと、DMA を使用する周辺機器との間のデータ転送のための Solaris DDI データアクセス機構の使用状況やハーネスチェックに関連するプロパティーです。

bofi-range-check

このプロパティーを設定すると、テストハーネスは PIO データアクセス関数に渡される引数の整合性をチェックします。

bofi-ddi-check

このプロパティーを設定すると、テストハーネスは、 ddi_map_regs_setup(9F) によって返される対応づけされたアドレスが、データアクセス関数のコンテキスト以外で使用されていないことを検証します。

bofi-sync-check

このプロパティーを設定すると、テストハーネスは DMA 関数の使用方法が正しいことを検証し、ドライバが仕様に準拠して ddi_dma_sync(9F) を使用していることを確認します。

ドライバのテスト

この節では、th_define(1M) および th_manage(1M) コマンドを使用して、障害を作成および投入する方法について説明します。

障害の作成

th_define ユーティリティーは、errdef を定義するための、bofi デバイスドライバへのインタフェースを提供します。1 つの errdef が、デバイスドライバによるハードウェアへのアクセスを破壊する方法に関する 1 つの仕様に対応します。th_define のコマンド行引数は、投入する障害の正確な種類を指定します。指定した引数によって矛盾のない errdef が定義される場合、th_define プロセスは bofi ドライバに errdef を格納します。errdef で定められている基準に達するまで、プロセスは一時停止状態になります。実際には、アクセスカウントが 0 になると一時停止状態が終了します。

障害の投入

テストハーネスはデータアクセスのレベルで動作します。データアクセスには次のような特性があります。

テストハーネスはデータアクセスを横取りし、適切な障害をドライバに投入します。th_define(1M) コマンドで指定された errdef によって、次の情報がエンコードされます。

errdef でフレームワークの障害をシミュレートするには、-a acc_chk オプションを使用します。

障害投入プロセス

障害投入のプロセスには 2 つの段階があります。

  1. th_define(1M) コマンドを使用して errdef を作成します。

    errdef を作成するときは、定義を格納する bofi ドライバにテスト定義を渡し、th_manage(1M) コマンドによって定義にアクセスできるようにします。

  2. ワークロードを作成し、th_manage コマンドを使用して errdef を起動および管理します。

    th_manage コマンドは、bofi ハーネスドライバが認識する各種の ioctl へのユーザーインタフェースです。th_manage コマンドはドライバの名前およびインスタンスのレベルで動作し、アクセスハンドルを列挙する get_handles、errdef を起動する start、errdef を停止する stop などのコマンドを含んでいます。

    errdef を起動すると、対象となるデータアクセスで障害が発生します。th_manage ユーティリティーは、errdef の現在の状態を表示する broadcast と、errdef をクリアする clear_errors の各コマンドをサポートします。

    詳細は、th_define(1M) および th_manage(1M) のマニュアルページを参照してください。

テストハーネスの警告

次の方法で警告メッセージを処理するようにテストハーネスを構成できます。

2 番目の方法を使用すると、問題の根本原因を特定しやすくなります。

bofi-range-check プロパティーの値を warn に設定した場合、テスト対象のドライバによる DDI 関数の範囲違反をハーネスが検出した時点で、ハーネスは次のメッセージを出力します (パニック動作が設定されている場合はパニック状態に移行します)。

ddi_getX() out of range addr %x not in %x
ddi_putX() out of range addr %x not in %x
ddi_rep_getX() out of range addr %x not in %x
ddi_rep_putX() out of range addr %x not in %x

X は 8、16、32、または 64 です。

ハーネスが 1000 を超える割り込みを挿入するように要求されており、ドライバが割り込みジャバーを検出しない場合、次のメッセージが出力されます。

undetected interrupt jabber - %s %d

スクリプトによるテストプロセスの自動化

th_define(1M) ユーティリティーのロギングアクセスタイプを使用すると、障害投入テストスクリプトを作成できます。

# th_define -n name -i instance -a log [-e fixup_script]

th_define コマンドはインスタンスをオフラインにし、またオンラインに戻します。th_define は次に、fixup_script によって記述されたワークロードを実行し、ドライバインスタンスが行う入出力アクセスをログに記録します。

fixup_script は、省略可能ないくつかの引数を指定して 2 回呼び出されます。このスクリプトはインスタンスがオフラインにされる直前に 1 回呼び出され、オンラインに戻されたあとにふたたび呼び出されます。

次の変数が、呼び出される実行可能ファイルの環境に渡されます。

DRIVER_PATH

インスタンスのデバイスパス

DRIVER_INSTANCE

ドライバのインスタンス番号

DRIVER_UNCONFIGURE

インスタンスが間もなくオフラインにされるときは 1 に設定

DRIVER_CONFIGURE

インスタンスがオンラインに戻されたときは 1 に設定

fixup_script は通常、テスト中のデバイスがオフラインになってもよい状態 (未構成) であること、またはエラー投入に適した状態 (構成済み、エラーなし、ワークロードを処理中など) であることを確認します。次に示すのは、ネットワークドライバ用の最小限のスクリプトの例です。

#!/bin/ksh
driver=xyznetdrv
ifnum=$driver$DRIVER_INSTANCE
 
if [[ $DRIVER_CONFIGURE = 1 ]]; then
   ifconfig $ifnum plumb    
   ifconfig $ifnum ...    
   ifworkload start $ifnum
elif [[ $DRIVER_UNCONFIGURE = 1 ]]; then    
   ifworkload stop $ifnum    
   ifconfig $ifnum down    
   ifconfig $ifnum unplumb
fi
exit $?

注 - ifworkload コマンドは、バックグラウンドタスクとしてワークロードを開始する必要があります。障害の投入は、fixup_script がテスト中のドライバを構成し、オンラインに戻したあとに行われます (DRIVER_CONFIGURE は 1 に設定されます)。


-e fixup_script オプションを指定する場合、コマンド行の最後のオプションとして指定する必要があります。-e オプションを指定しない場合、デフォルトのスクリプトが使用されます。デフォルトのスクリプトは、テスト中のデバイスのオフライン化とオンライン化を繰り返し試行します。そのため、ワークロードはドライバの attach() および detach() パスで構成されます。

結果のログは、自動での障害投入テストの実行に適した、いくつかの実行可能スクリプトに変換されます。これらのスクリプトは、driver.test.id という名前で、カレントディレクトリのサブディレクトリに作成されます。スクリプトは、fixup_script によって記述されたワークロードの実行中、一度に 1 つずつ障害を投入します。

ドライバのテスト担当者は、テスト自動化プロセスによって生成された errdef の大部分を制御できます。th_define(1M) のマニュアルページを参照してください。

テスト担当者がテストスクリプトに適した範囲のワークロードを選択すると、ハーネスはドライバ強化の多くの側面をテストできます。ただし、すべてを網羅するためには、テスト担当者が追加のテストケースを手作業で作成しなければならない場合があります。これらのケースをテストスクリプトに追加します。テストを時間内に完了させるために、重複したテストケースを手作業で削除することが必要になる場合があります。

自動テストプロセス

自動テストのプロセスは、次のようになります。

  1. ドライバのどの部分をテストするかを識別します。

    次に示すような、ドライバがハードウェアと対話する部分はすべてテストします。

    • 接続と切り離し

    • スタック下の plumb と unplumb

    • 通常のデータ転送

    • ドキュメント化されたデバッグモード

    使用モードごとに別個のワークロードスクリプト (fixup_script) を生成する必要があります。

  2. 使用モードごとに、デバイスを設定および設定解除し、ワークロードを作成および終了する実行可能プログラム ( fixup_script) を準備します。

  3. errdef とアクセスの種類 (-a log) を指定して、th_define(1M) コマンドを実行します。

  4. ログがいっぱいになるまで待ちます。

    ログの内容は bofi ドライバの内部バッファーのダンプです。このデータはスクリプトの先頭部分に含まれています。

    ログの作成には数秒から数分かかるため、th_manage broadcast コマンドを使用して進捗状況を確認します。

  5. 作成されたテストディレクトリに移動し、マスターテストスクリプトを実行します。

    マスタースクリプトは、生成された個々のテストスクリプトを順に実行します。レジスタセットごとに個別のテストスクリプトが生成されます。

  6. 分析のために結果を格納します。

    success (corruption reported)success (corruption undetected) のような成功したテスト結果は、テスト中のドライバが正常に動作していることを示します。ドライバが障害を報告したあとにサービスへの影響を報告できなかったことをハーネスが検出した場合や、アクセスハンドルまたは DMA ハンドルが障害とマーク付けされたことをドライバが検出できない場合、failure (no service impact reported) という結果が報告されます。

    test not triggered エラーが出力にいくつか含まれていても問題はありません。ただし、そのようなエラーが多数にのぼる場合は、テストが適切に機能していないことを示しています。これらのエラーは、テストスクリプトが生成されたときと同じレジスタにドライバがアクセスしていない場合に発生することがあります。

  7. ドライバの複数のインスタンスに対して同時にテストを実行し、エラーパスのマルチスレッド化をテストします。

    たとえば、th_define コマンドは毎回、テストスクリプトとマスタースクリプトを収めたディレクトリを新しく作成します。

    # th_define -n xyznetdrv -i 0 -a log -e script
    # th_define -n xyznetdrv -i 1 -a log -e script

    マスタースクリプトが作成されたら、それらを同時に実行します。


    注 - 生成されたスクリプトは、ログ記録対象の errdef がアクティブであった期間中に記録されたログ内容に基づく障害投入のシミュレーションのみを実行します。開発者がワークロードを定義するときは、必要な結果が確実にログに記録されるようにします。また、結果のログと障害投入仕様を分析します。生成されたテストスクリプトによるハードウェアアクセスの範囲が、必要な基準を満たしていることを確認してください。