STR91XX

写真(2016-05-21 10.49)
お約束ですが、このページのいかなる記載においても著者は一切の責任をおいません。
2016/05/20-

HardOffでRT1310かと思い524円で購入したルータがSTR9102で、FreeBSDの arm/cavium/cns11xxにコードがあるようなので、試してみる事にした。 このチップはもともとStar Semiconductorという会社の製品だったが、この会社は 2008年にCaviumに買収されたようだ。Star Semiconducto時代の製品名がSTR91XXで CaviumになってからはCNS11XXとなったようだ。 チップは2007年47週の製造でarm v4系(922)だがメモリが64Mでフラッシュが 8Mと十分な容量がある。シリアルはTX,RXなどのシルク印刷があり38400BPSだった。 ブートはARMboot 1.1.0 (Sep 13 2007 - 14:41:53)が入って いて起動時に^Cで止める事ができ、ネットワークもちゃんと使えた。ARMBootはU-Boot の元となったPPCBootから派生したプロジェクトだったみたいだ。 データーシートもネットで入手できる。 純正ファームブートログ

2008年くらいの製品だと思うが、この当時としては珍しいギガのスイッチのチップを 外付けにしている。ヒートシンクが貼られていて確認できないがVitesseという会社の VSC7385のようだ。

FreeBSDのコードはYohanes Nugrohoさんが作られて こちらにページがあった。 いまのところこのコードはeventtimerのサポートがなかったりFDTにも対応してない。 ページのコメントにFreeBSD 10でBootしないという書き込みがある。

メモリは0x00000000(0x20000000)からありフラッシュは0x10000000からあるようだ。

国内にも NetBSDを試されている方がいる模様。

RT1310の設定をコピーして書き換えイメージは数時間でできた。しかしイメージを tfpboot/bootmしても全く返事がないので、とりあえず得意のリセット作戦。 まずはBootでリセットしてみる。

STR9100>mw.b 0x77000004 0

アセンブラで書くとこんな感じ。

        /* reset code */
        ldr     r0,=0x77000000
        ldr     r2,=0
        strb    r2, [r0, #+4]
resetwait:
        nop
        b       resetwait

当初、0x00000000なアドレスからのカーネルを作っていたところ、Bootがハングアップ してしまい、0x50000からのビルドにした。どうもこのボードのBootはメモリの先頭部分 を利用しているようだ。Bootが展開できて、とりあえずlocore-v4.Sが実行されている のは確認できたがtranslate_va_to_paで落ちる。何でだろう。

STR9100>bootm
## Booting image at 00800000 ...
   Image Name:   FreeBSD Kernel Image
   Image Type:   ARM Linux Kernel Image (gzip compressed)
   Data Size:    1263205 Bytes = 1233 kB = 1 MB
   Load Address: 000500e0
   Entry Point:  000500e0
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

data abort
pc : [<00000134>]    lr : [<00050138>]
sp : 0003b30c  ip : 78000000  fp : 00000000
r10: 00800040  r9 : 00000000  r8 : 000000f2
r7 : 600000d3  r6 : 0003b63c  r5 : 00000000  r4 : 000500e0
r3 : 00000000  r2 : c0000000  r1 : c0314000  r0 : 00314000
Flags: nZCv  IRQs off  FIQs off  Mode UND_32
Resetting CPU ...

### ERROR ### Please RESET the board ###

ARMのアセンブラはここ が参考になる。

std.econaには"CONF_CFLAGS=-march=armv4"とあるが、gccでこのオプションを使うと geom_lavelなどでコンパイルが通らなくなる。CFLAGSに-mno-thumb-interworkの設定が 必要で環境変数にセットしておくと通った。sys/conf/Makefile.armにCFLAGS.gccと あるが、ZRouterではこれを元にコンパイルしているが効いていないようだ。 と思ったが、カーネル本体のビルドには効いていて、モジュールのビルドの時には 効いていないような気がする。

arm/locore-v4.Sは元々arm/locore.Sだったのを2014年にv4とv6に分けたみたいだ。

なんとデータシートには922互換とあるがTではなくてarmv4が正しいようだ。このため 4T以降でサポートされたRETで使われるbx命令が無くarmv4t以上でコンパイルすると この命令が使われるためRETURNできなくて落ちていた。

armv4なコード

c005021c <translate_va_to_pa>:
c005021c:       e5901000        ldr     r1, [r0]
c0050220:       e0412000        sub     r2, r1, r0
c0050224:       e5901004        ldr     r1, [r0, #4]
c0050228:       e0410002        sub     r0, r1, r2
c005022c:       e1a0f00e        mov     pc, lr

armv4tなコード

c0000230 <translate_va_to_pa>:
c0000230:       e5901000        ldr     r1, [r0]
c0000234:       e0412000        sub     r2, r1, r0
c0000238:       e5901004        ldr     r1, [r0, #4]
c000023c:       e0410002        sub     r0, r1, r2
c0000240:       e12fff1e        bx      lr

このチップはFA526というタイプでFreeBSDにはMMUの設定などの専用のアセンブラコード が用意されている。

とりあえずブートログでました。(2016/05/23)

initを起動したところで落ちていたが、よくよく考えてみるとユーザランドも armv4でコンパイルしなければいけなかった。

initは実行されるようになったがシングルユーザのshを起動する前で "Jan 1 00:00:08"だけ出力して固まる。固まった後にUSBメモリの抜き差しを してもまったくメッセージが出ないので、完全に落ちているようだ。 DDBにも落ちないのは非常に困り果てる。

エクセプションが起きても拾えるはずなのだが、拾えずダブルフォルトすること あるのかな。。。

よくよくコードを追ってみると、uart_dev_ns8250.cの送信部分にbroken_txfifo という怪しげな変数がある。これを設定してみたところちゃんと文字の出力が されるようになった。この値はhints(sysctl)やFDTから設定できるようなのだが他の sdtを見てみると設定しているものがある。ただsysctlのメッセージはQUMEのバグの 多応のようなコメントだけでちょっと不親切かも。

UARTのコードはuart_cpu_hogeとuart_bus_hogeというコードで構成されているが、 これらは起動からinitさんの手前までがcpuでそれ以降がbusで処理されるよいう 流れになる。cpuの方はTXの割り込みは使わず、busになった時に割り込みを使い 始める。

シングルユーザのシェル選択のプロンプトまで進んだが、以前ハングアップする。 割り込みにデバッグライトを入れてみて、タイマーの割り込みも止まってしまうので、 またまた完全に落ちている模様。。。

試しにマルチユーザまで進めると、loginプロンプトまでたどり着くがやはりハング アップする。consoleのtty(uart)に対してreadを行ったタイミングで落ちているような 感じだ。ttyに対するreadは受信データがあればそれを返し無ければ空で返ることに なる。受信データは普通は割り込みで拾われている。

ttyは昔はsioというドライバだったがFreeBSD 8の頃にuartドライバに取り替えられた ようだ。uartのパラメータでshiftというのがあるが、これはレジスタのバウンダリ を設定するもので0であれば1バイト毎で1であれば2バイトで2で4バイト毎にレジスタが 並んでいる事を示す。

かなりはまりまくっているが、乗りかかった船なので、まだ調べている。シングル ユーザでシェルのところで落ちるが、マルチユーザまで進めると今度はログインの ところで落ちる。入力を開いたところで落ちているような気もする。落ちる前にログが 出ている時に入力するとエコーバックされるので、uartの入力がまったく機能して いないわけでもなさそう。

broken_txfifoは進んでいるように見えるが、実は根本的な問題を先送りしている だけでしかなさそう。initさんをWRITEONLYでコンソールをつかませると落ちない。 9-Currentでは実装した人以外にも試していたようで、ちゃんと動いていたような 感じだから何が影響しているのかな。。。

完全に落ちているのかUARTだけが死んでいるのかはこのデバイスではUSBデバイスを つないで、アクティブになるかどうかで判断できたりする。

kern/tty.cをwirteをダミーにして起動するとログインプロンプトの前まで進むが ログインプロンプトが出ない。なにか他に問題があるのかな。。。

どうもreadは確実に落ちるが、writeでも落ちる事があるみたい。。。こんなに不安定な UARTははじめてだ。uartのコードには8250系なはずなのにいろいろなデバイスのコード が用意されているのが、不具合対応の対応のためなんだろう。UARTは最も古い インターフェースなのでしかたがないのかな。

OSで問題が起きた時には、デバッガーに落ちる、リブートする、ハングアップするの ケースがある。ハングアップはあまり起きえないのだが、可能性は自分からhaltするとか クロックを止めてしまうとか、DMAがCPUを止めたままにするとか、メモリが見えなくなる とかかな。

JTAGのピンがあるので、UrJTAGでみてみたがdetectできない。。。

UARTのFIFOに16バイト突っ込んだ後ハングアップしているように見える。broken_txfifo をセットするとちょっと先まで進むのでUARTアクセスから戻った時に問題を起こしている ような感じ。

Yohanesさんのページにあるカーネルとrootfsだとちゃんとloginまで進む。この バイナリは9-CURRENTの時代に作られたようだ。cns11xxのポートは8-CURRENT時代から 初めて9-RELEASEには終わっていたようだ。9.0-RELEASEのコードでビルドすると ちゃんと動くようだ。

10.1-RELEASEのソースをビルドしても場所は違うがカーネル起動時にハングアップする。 考えられる可能性は、9から10でcns11xxのコードの修正が影響しているか、armサポート の修正が影響しているか、kernの修正が影響しているかのどれかだと思われる。

clangのバージョンが変わっていたので、試しにビルドしてみたがやはりarmv4での ビルドはうまくいかない。clangはarmv4t以降のサポートなんだと思われる。 (2017/04/14)

とりあえずgccでビルドしてカーネルを起動するとmountrootのところでハングする。 私がいじるまえの10Rでも同じところで、ハングしていたので、修正の問題では ないと思われる。とはいえなんでだろう。。。

このターゲットは遅いが、メモリ,Flashも大きいし、USB付いてるし、ネットワークも GIGAだったりして、結構気に入っているので、どうにか動くようにしたいのだが。。。

以前は日付を出力して行の途中でハングしていたのだが、今はハングのしかたが違う。

もとものとコードを実行するとuartが "Non-standard ns8250 class UART with FIFOs"となっていたのだが、これはtimer よりも前にロードされてDELAYがビジーループで実行されるためであった。dtsでuartを timerよりも前に書くと同じようになる。

rootfsがmountできないと、割り込みが上がらなくなり落ちている。なぜかrootfsが mount出来るとtimer割り込みは生きているのだが、ハングアップしたような状態に なる。ところが10分くらいたってから"random: unblocking device."が出力される。 別々の問題にも思えるがどうなのだろう。

この割り込みが上がらなくなるのは2015年の暮れに発生するようになったbcm/mips系 でハングしているのと同じ原因ではないのだろうか。

INTRNGがkernに入ったタイミングを疑っているのだが、原因が分からない。INTRNGで なくてもハングする。そもそもkern/subr_intr.cはarm/armから移された物で当初は armだけが対象だったはずなので、bcm/mipsに影響が出たとは考えにくいのだが。

rootfsがmount出来ないときにハングするのはkern/vfs_mountroot.cでpauseを2度呼んだ 時に起きているようだ。

割り込みが上がらなくなっているのか、そもそもCPUが落ちているのかは分からない。 デバッガーに落ちずにCPUが落ちているってありうるのかな。もしCPUが無権ループに 入っても割り込みは上がるはずなのだが。

armのintrの処理は cpsrというレジスタで制御できるみたい。 arm/include/cpufunc.hの中にintr_disable()があるが、これを誤って呼んでるのかな。

mizhkaさんの話ではbcm/mips74でも同じような現象があって、ワークアラウンドを 入れたという事であった。

こつこつデバッグしたところkern/vfs_mountroot.cのpauseで落ちている。 やはり直接的な不具合ではなさげだ。

        do {
                pause("rmdev", delay);
                timeout -= delay;
        } while (timeout > 0 && !parse_mount_dev_present(dev));

mount出来る場合は直前のparse_mount_dev_present()で処理されるのでここのpause は通らないのでここでは落ちません。

各種カーネルデバッグオプションを設定してみてもなにも出てこない。。。

pauseを呼ぶ前のkdbのpsの結果

mountroot: waiting for device /dev/cfid0s.rootfs.uzip...
KDB: enter: Break to debugger
[ thread pid 1 tid 100001 ]
Stopped at      kdb_enter+0x40: ldrb    r15, [r15, r15, ror r15]!
db> ps    
  pid  ppid  pgrp   uid  state   wmesg   wchan       cmd
   16     0     0     0  DL      -       0xc039fa80  [soaiod4]
   15     0     0     0  DL      -       0xc039fa80  [soaiod3]
   14     0     0     0  DL      -       0xc039fa80  [soaiod2]
   13     0     0     0  DL      -       0xc039fa80  [soaiod1]
    9     0     0     0  DL      -       0xc033449c  [schedcpu]
    8     0     0     0  DL      vlruwt  0xc0a68730  [vnlru]
    7     0     0     0  DL      syncer  0xc03a0cec  [syncer]
    6     0     0     0  DL      psleep  0xc03a0080  [bufdaemon]
    5     0     0     0  DL      -       0xc03a0084  [bufspacedaemon]
    4     0     0     0  DL      pollid  0xc0333b5c  [idlepoll]
    3     0     0     0  DL      (threaded)          [pagedaemon]
100023                   D       psleep  0xc03a5310  [pagedaemon]
100031                   D       launds  0xc03a5318  [laundry: dom0]
100032                   D       umarcl  0xc03a4cc8  [uma]
    2     0     0     0  RL                          [rand_harvestq]
   12     0     0     0  DL      (threaded)          [geom]
100012                   D       -       0xc0330af8  [g_event]
100013                   D       -       0xc0330b00  [g_up]
100014                   D       -       0xc0330b04  [g_down]
   11     0     0     0  RL      (threaded)          [intr]
100003                   I                           [swi1: netisr 0]
100004                   I                           [swi3: vm]
100005                   RunQ                        [swi4: clock (0)]
100006                   I                           [swi5: fast taskq]
100008                   I                           [swi6: Giant taskq]
100009                   I                           [swi6: task queue]
100016                   I                           [swi0: uart]
100017                   I                           [econaarm0,20: ece0]
100018                   I                           [econaarm0,18: ece0]
100019                   I                           [econaarm0,22: ece0]
100020                   I                           [econaarm0,19: ece0]
   10     0     0     0  RL                          [idle]
    1     0     0     0  RL      CPU 0               [kernel]
    0     0     0     0  DLs     (threaded)          [kernel]
100000                   D       swapin  0xc0330f48  [swapper]
100007                   D       -       0xc0a4f580  [thread taskq]
100010                   D       -       0xc0a4f400  [aiod_kick taskq]
100011                   D       -       0xc0a4f380  [kqueue_ctx taskq]
100015                   D       -       0xc0a4d400  [cfid taskq]
100021                   D       -       0xc0a50600  [ece0 taskq]
100029                   D       -       0xc0b91580  [softirq_0]


ブートログ


Copyright (C) 2016 Hiroki Mori All Rights Reserved.