SSブログ

PowerBook G4の故障とその原因その6 [PowerBook G4故障のこと]

1GBメモリモジュールのために動かなくなっていたPowerBook G4 12"。メモリモジュールを買い替えずにすますことができるのか?!
緊迫と衝撃の第6回!!

アホなこと言うとらんと、どうするかと言えば前回

  1. mmap()で仮想メモリを確保する
  2. それを全部「0」でうめる
  3. L2キャッシュがいっぱいになるまで繰り返す
  4. キャッシュから追い出されたと思われるメモリ領域をもう一度読み出して内容をチェックする
  5. 書いた内容と違うページがあったらそれをロックする
という行き当たりばったりに問題の物理ページに行き着くまでやる、と言う方針にした。 そこでこんなのを書いた。
int main (int argc, const char * argv[])
{
    static const int    cachesize = 512 * 1024;
    char    **mmaptable;
    int     ret;
    int     n = 0, leap;
    int     pagesize = getpagesize();
    int     maxsize = 1024 * 1024 * 1024 / pagesize;
    int     leaplength = cachesize / pagesize;
    mmaptable = (char **)malloc(maxsize);
	
    while (n < maxsize) {
        fprintf(stderr, "*");
        for (leap = 0 ; leap < leaplength ; leap ++) {   //   (1)
            if (mmapandfill(mmaptable + n + leap, pagesize) != OK) {
                fprintf(stderr, "error in mmap : %s\n",
                            strerror(errno));
                return -1;
            }
        }
        for (leap = 0 ; leap < leaplength ; leap ++) {   //   (2)
            if (checkmap(*(mmaptable + n + leap), pagesize) != OK) {
                if (mlock(*(mmaptable + n + leap), pagesize) < 0) //(3)
                    fprintf(stderr, "error in mlock : %s\n",
                                strerror(errno));
                for (leap ++ ; leap < leaplength ; leap ++)   //  (4)
                    munmap(*(mmaptable + n + leap), pagesize);
                while (-- n >= 0)
                    munmap(*(mmaptable + n), pagesize);    //  (4)
                fprintf(stderr,
                        "got a bad page and will go to sleep\n");
                sleep(31536000);
                return 0;
            }
        }
        n += leaplength;
    }
    fprintf(stderr, "no memory error is found. quitting...\n");
    return -1;
}
で、この中で呼んでるふたつの関数
static int  mmapandfill(char **addrp, int pagesize)
{
    char    *bp, *addrend;
    *addrp = (char *)mmap(0, pagesize, PROT_READ | PROT_WRITE,
                            MAP_PRIVATE | MAP_ANON, -1, 0);  // (5)
    if (*addrp == MAP_FAILED)
        return CNT;
	
    addrend = *addrp + pagesize;
    bp = *addrp;
    while (bp < addrend) {   //  (6)
        *bp = '\0';
        bp ++;
    }
    return OK;
}

static int  checkmap(char *addrp, int pagesize)
{
    char    *addrend = addrp + pagesize;
    while (addrp < addrend) {
        if (*addrp != '\0') {      //   (7)
            fprintf(stderr, "found %X\n", (unsigned int)(*addrp));
            return NG;
        }
        addrp ++;
    }
    return OK;
}
こんなの。書き方まで行き当たりばったりになって読み辛いけど、ようするにやろうとしていることは前回と同じ、mmap()でメモリ領域を要求(5)して、問題ページをmlock()でロック(3)する。

前回は物理メモリをマップしようとしてOSに断られてうまく行かなかった。今回は、(1)のループでとにかく仮想ページを要求し続ける。そこに(6)で0を書き込む。そのあと(7)でチェックして0でないところが見つかればそのページをmlock()する。

問題のメモリ領域がどこの仮想メモリにマップされるかわからないし、書いてすぐチェックしたのではCPUのキャッシュを読み書きするだけなので、キャッシュよりも大きいバイト数を書き込んで(leaplengthページ)そのあと、チェックしている。こうすれば古いデータはキャッシュから追い出される。

さて、件のPowerBookをターゲットディスクモードにしてこれをコピーして、シングルユーザモードで立ち上げて実行した。

localhost:/ root: ./a.out &
*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************found FFFFFF80
got a bad page and will go to sleep
やたっ。188MBチェックし終わって捕まえた。mlock()もエラーを返してないみたいなので成功しているはず。物理メモリの前の方からmmapして行くとするとこないだのmemtestで行き着いた問題物理アドレス0x05cb3090は(前の方50MBはすでにOSが確保してしまっているので)空き領域の先頭から50MBほどのはずで、3倍余分にかかっていることになる。ちょっとおかしい気がするが、すでにページテーブルが入れ替わっているとすればあり得る。

psを見てみると

localhost:/ root: ps
  PID TT  STAT       TIME COMMAND
    2 ??  Ss      0:00.07 -sh
    6 ??  S       0:42.99 ./a.out
    7 ??  R+      0:00.01 ps
localhost:/ root: 
でまだ生きていて1年間スリープに入っている。とうとう成功したか!?

いちおう確認のためもういちど走らせる。こんどは前回のが問題ページをロックしているはずなので、エラーを起こすメモリは見つからなくなっているはず。

localhost:/ root: ./a.out &
*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************found FFFFFF80
got a bad page and will go to sleep
ありゃあ???psで確認すると
localhost:/ root: ps
  PID TT  STAT       TIME COMMAND
    2 ??  Ss      0:00.07 -sh
    6 ??  S       0:42.99 ./a.out
    8 ??  S       0:43.01 ./a.out
    9 ??  R+      0:00.01 ps
localhost:/ root: 
おっかしいなあ。mlock()ができてないのかなあ。しょうがないのでもういちどまえやったmemtestを動かしてみると

.....
Allocated memory: 1187MB (1244761152 bytes) at local address 0x03008000
Attempting memory lock... locked successfully
Partitioning memory into 2 comparison buffers...
Buffer A: 593MB (622380576 bytes) starts at local address 0x03008000
Buffer B: 593MB (622380576 bytes) starts at local address 0x28194620

Running 1 test sequence... (CTRL-C to quit)

Test sequence 1 of 1:

Running tests on full 1187MB region...
  Stuck Address       :                 setting  1 of 16testing  1 of 16

FAILURE! Data mismatch at local address 0x05dbc090
Actual Data: 0x059bc090
.....(省略)
で、やっぱりエラーバイトが見つかる。おかしいなあ。でもちょっとまてよ、前回やったのと比較して
localhost:/ root: diff result.txt r2.txt > /diff.txt
localhost:/ root: more /diff.txt
として一部だけ取り出してみると
.....
37,38c40,41
< FAILURE! Data mismatch at local BUFA address 0x05cb3090, BUFB address 0x2aec9ed0
< BUFA Data: 0x7fb816e6, BUFB Data: 0x7ff816e6
---
> FAILURE! Data mismatch at local BUFA address 0x05dbc090, BUFB address 0x2af486b0
> BUFA Data: 0x1dbce352, BUFB Data: 0x1d3ce352
.....
ありゃ?アドレスが違ってる。しかも微妙に。どういうこと???逃げ水のようなエラー。

なにか根本的に考え方が間違ってるのかなあ?おっかしいなあ。これがうまく行ったらSystem DomainのLaunchDaemonsに登録してブートのときにこいつを立ち上げてロックしてしまおう、そのためにlaunchdのdaemonの*.plistの書き方でも勉強しようと思っていたのに....

がっかり。くやしい。これはメモリのひとつのセルが壊れた、とかいう問題じゃないのかなあ。セルだとしたら物理アドレスが変わるなんてことは無いよなあ。物理アドレスって何かの拍子に変わるのか? んなわけないよなあ。

しかしこれ、仕事でやってたら費やした工数でメモリモジュールなんかあっさり買えるな。残るは最後の手段かなあ。ひょっとしたらそれでは解決しなかったりして。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立06/13献立06/14 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。