月別アーカイブ: 2017年6月

[Linux] User I/O

今更ながら User I/O (UIO) を使ってみました.UIO は 2.6.23-rc1 で kernel に merge された機能で,ドライバモジュールを書くことなくハードウェア資源を userland からアクセスできる手段を提供します.

I/O にアクセスするだけなら /dev/mem を mmap すれば実現できますが,アドレスが制限されないため安全性が担保できません.UIO では予め使用する領域を定義するとともに,割込み応答もできるようになります.

UIO を利用可能にするには,下記の1行目の CONFIG を有効にします.さらに 2行目の CONFIG を有効にすることで,platform driver として扱うことができ,device tree で I/O 領域や割込みが定義できるようになります(もちろん CONFIG_OF=y が必要).CONFIG_UIO_PDRV_GENIRQ を ”m” にしているのは,ユーザが I/O を使い始めるタイミングを userland から制御できるようにするためです.

CONFIG_UIO=y
CONFIG_UIO_PDRV_GENIRQ=m

device tree には次のようなノードを追加します.reg には使用したい I/O アドレスを page 単位で指定します.これは page 単位(default は 4KB)である必要があります.この領域は例では2つ定義していますが,ノードごとに 5 つまで指定できます.interrupts はノードに対して割込み番号を 1つだけ指定できます.
※ interrupts の数値の意味はアーキテクチャにより異なります.ARM GIC では 0 は SPI, 100 は物理割込み番号の32を引いた値,4はレベル割込みを表します.

/{
        uio {
                compatible = "generic-uio", "myuio";
                reg = <0x40000000 0x1000>,<0x41000000 0x1000>;
                interrupts = <0 100 4>;
        };
};

UIO のノードを1つ作成すると,対応するデバイスファイル(/dev/uioX)が1つできます.マイナー番号は昇順に振られるため,複数のノードを作成するとuio0から順にデバイスファイルが対応付けられます.それぞれのデバイスファイルを制御することでノードごとに定義した割込みを同時に扱うことができます.

ターゲット上では modprobe (insmod) でドライバを有効にしますが,その際に引数に devicetree で定義した compatible 文字列を指定します.これで定義した I/O 領域や割込みが取り込まれ,デバイスファイルが作成されます.

# modprobe uio_pdrv_genirq.ko of_id=myuio

ユーザプログラムでは通常のドライバと同様にデバイスファイルを open した後,mmap すれば device tree で定義した I/O 領域へのアクセスが可能になります.mmap で指定する offset は page 単位で連続した相対アドレスです.例では,上記 0x40000000 が base1,0x41000000 が base2 に にマップされます.

void main()
{
        int fd;
        void __iomem *base1, *base2;

        fd = open("/dev/uio0", O_RDWR);
        base1 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
        base2 = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 1 * PAGE_SIZE);
        ...
        munmap(base2);
        munmap(base1);
        close(fd);
}

割込みを待つ場合は,まず割込みを許可するためにデバイスファイルに 1 を書き込みます.その後,read() を呼ぶと割込みが入るまでブロックします.再度割込みを待つ場合は再びデバイスファイルに 1 を書いて割込みを許可します.タイムアウトを追加したい場合は,ppoll() で待って read() で読み出す処理を行うことで実現できます.

void main()
{
        int fd, irqsw, count;
        fd = open("/dev/uio0", O_RDWR);

        irqsw = 1;
        write(fd, &irqsw, sizeof(irqsw)); /* enable interrupt */
        ...
        read(fd, &count, sizeof(count)); /* wait for interrupt */
        ...
        irqsw = 0;
        write(fd, &irqsw, sizeof(irqsw));  /* disable interrupt */
        close(fd);
}

ドライバを作る前に I/O を直接操作して動作を確かめたい場合や,ドライバを作るまでもないHardware制御を行いたいときに,UIO を使うと手軽に実現できます.また,諸事情により公開が難しい Proprietary Driver を作成せざるを得ない場合でも,UIO を使うことで  userland 上に実現することが可能です.

Open Source Summit Japan 2017

1年ぶりの更新になります.
先日有明のコンファレンスセンターにて開催された Open Source Summit Japan に参加してきました.このイベントは初参加で Community への貢献もまだまだの中で,全セッション英語とあってまずは雰囲気を知る機会で2日間参加しました.

最近は LinuxCon と ContainerCon と CloudOpen の統合,Automotive Linux Summit との共催で講演が多岐に渡って行われる反面,深い技術トピックが少なかったのが技術者・開発者としては寂しいところです.組込み Linux の開発関連は Automotive 側に話題が多く,OSSJ は Cloud や Server,Service の話題が多かったように思います.

KeyNote を一通り聞いた後,以下のセッション(とこの他いくつか)を聴講しました.

  • Building Debian-Based Products: Experiences in Collaboration
    • Debian の OE レシピと Image 作成のシステムを統合した話
  • Understanding SCHED_DEADLINE
    • EDF アルゴリズム(最もdeadlineが近いタスクに割り当てる)に基づくスケジューリングの話
  • Taking ARM Servers Mainstream: Designing, Building, and Deploying in the Real World
    • ARMv8 サーバにおける RHEL のソフトウェア・ハードウェア要件の話
  • Building, Deploying and Testing an Industrial Linux Platform
    • 工業向け Linux の長期間継続的なメンテナンス・テストの話
  • Adding new CPU architecture to QEMU
    • QEMU に新アーキを追加する際の translation の仕組みの話
  • Bare Metal Container
    • 遠隔サーバ上の OS 非依存のコンテナを扱うシステムの話

セッションの間はドリンクやクッキー,フルーツなどが自由に楽しめました.日本開催ということでお約束の抹茶ケーキやおかきセットなどもありました.ランチは自力解決とはいえ,有明という立地上選択肢が少なく参加者は大変だったかもしれません.

参加期間中,Community の方々に交じってランチや夕食に 同席させていただいたのですが,せっかくの機会なのに英語力の無さでいろいろ申し訳ない応答になったのが無念でした…