APC8750にNetBSD/evbarmを移植するための記録 9/7 その1
2014/01/13(月) 21:11 NetBSD はてブ情報 はてブに登録 はてブ数

ずいぶん時間が過ぎ去った。割り込みコントローラの続き。

割り込みコントローラのアドレスをダンプしてみる
WMT # md.l d8140000
d8140000: 0000003f 0000003f 0000003f 00000000    ?...?...?.......
d8140010: 00000000 00000000 00000000 00000000    ................
d8140020: 00000000 00000000 00000000 00000000    ................
d8140030: 00000000 00000000 00000000 00000000    ................
d8140040: 00000000 00000000 00000000 00000000    ................
d8140050: 00000000 00000000 00000000 00000000    ................
d8140060: 00000000 00000000 00000000 00000000    ................
d8140070: 00000000 00000000 00000000 00000000    ................
d8140080: 00000000 00000000 00000000 00000000    ................
d8140090: 00000000 00000000 00000000 00000000    ................
d81400a0: 00000000 00000000 00000000 00000000    ................
d81400b0: 00000000 00000000 00000000 00000000    ................
d81400c0: 00000000 00000000 00000000 00000000    ................
d81400d0: 00000000 00000000 00000000 00000000    ................
d81400e0: 00000000 00000000 00000000 00000000    ................
d81400f0: 00000000 00000000 00000000 00000000    ................
最初の三つが気になる。
u-bootも見たほうがいいか?
うーん、探せない...

まぁ、触ってみるか。
        /* debug */
        for (i = 0; i < 10; i++) {
                aprint_normal("icu-debug: ");
                debug = bus_space_read_4(sc->sc_iot, sc->sc_ioh, i);
                aprint_normal("%08x  %08x\n", (int)WM8750_IC0_BASE + i * 4, debug);
        }
とかattachルーチンにいれてみた。

bus_space_read_4の引き数の最後は割り込みコントローラの先頭アドレス(0xd8140000)からの相対位置でよい。最初は絶対アドレスで書いていたら
wmicu0 at obio0 addr 0xd8140000-0xd814ffff
icu-debug:
uvm_fault(0xc027dfb4, d6280000, 1) -> e
Fatal kernel mode data abort: 'Translation Fault (S)'
trapframe: 0xc0296d80
FSR=00000005, FAR=d6280000, spsr=200001d3
r0 =00000000, r1 =fe140000, r2 =d8140000, r3 =c000e840
r4 =c1a2a668, r5 =d8140000, r6 =d8140028, r7 =c01b16dc
r8 =c018c0a8, r9 =c0180744, r10=00000000, r11=c0296dec
r12=c0296da8, ssp=c0296dd0, slr=c01659dc, pc =c000e844

Stopped in pid 0.1 (system) at  netbsd:generic_bs_r_4+0x4:      ldr     r0, [r1, r2]
0xc0296dec: netbsd:wm8750_icu_attach+0xc
0xc0296e18: netbsd:config_attach_loc+0x190
0xc0296e30: netbsd:config_found+0x2c
0xc0296e58: netbsd:obio_attach_critical+0x40
0xc0296e70: netbsd:obio_attach+0x38
0xc0296e9c: netbsd:config_attach_loc+0x190
0xc0296eb0: netbsd:config_attach+0x24
0xc0296eec: netbsd:mainbussearch+0x8c
0xc0296f30: netbsd:config_search_loc+0x134
0xc0296f44: netbsd:config_search_ia+0x1c
0xc0296f70: netbsd:config_attach_loc+0x190
0xc0296f84: netbsd:config_attach+0x24
0xc0296f9c: netbsd:cpu_configure+0x30
0xc0296fec: netbsd:main+0x1fc
0xc0296ffc: netbsd:kernel_text+0x50
db>
などと言って落ちた。

もちろん、先のコードでも
icu-debug: d8140000  0000003f
icu-debug: data_abort_handler: data_aborts fsr=0x1 far=0xfe140001
Fatal kernel mode data abort: 'Alignment Fault 1'
trapframe: 0xc0296d78
FSR=00000001, FAR=fe140001, spsr=200001d3
r0 =00000000, r1 =fe140000, r2 =00000001, r3 =c000e840
r4 =c1a2a668, r5 =00000001, r6 =d8140004, r7 =00000000
r8 =c018c0a8, r9 =c0180744, r10=00000000, r11=c0296dec
r12=c0296da4, ssp=c0296dcc, slr=c01659e0, pc =c000e844

Stopped in pid 0.1 (system) at  netbsd:generic_bs_r_4+0x4:      ldr     r0, [r1, r2]
0xc0296dec: netbsd:wm8750_icu_attach+0xc
0xc0296e18: netbsd:config_attach_loc+0x190
0xc0296e30: netbsd:config_found+0x2c
0xc0296e58: netbsd:obio_attach_critical+0x40
0xc0296e70: netbsd:obio_attach+0x38
0xc0296e9c: netbsd:config_attach_loc+0x190
0xc0296eb0: netbsd:config_attach+0x24
0xc0296eec: netbsd:mainbussearch+0x8c
0xc0296f30: netbsd:config_search_loc+0x134
0xc0296f44: netbsd:config_search_ia+0x1c
0xc0296f70: netbsd:config_attach_loc+0x190
0xc0296f84: netbsd:config_attach+0x24
0xc0296f9c: netbsd:cpu_configure+0x30
0xc0296fec: netbsd:main+0x1fc
0xc0296ffc: netbsd:kernel_text+0x50
db>
と言って落ちる。一刻みのアドレスでアクセスできるわけないのでアラインメントがおかしいといって。おちる。
comprobe1 0
</wm8750_uart_match rv=0>
wmicu0 at obio0 addr 0xd8140000-0xd814ffff
icu-debug: d8140000  0000003f
icu-debug: d8140004  0000003f
icu-debug: d8140008  0000003f
icu-debug: d814000c  00000000
icu-debug: d8140010  00000000
icu-debug: d8140014  00000000

中略

icu-debug: d81400f8  00000000
icu-debug: d81400fc  00000000
<wm8750_uart_match>
com0 at obio0 addr 0xd8200000-0xd820ffff intr 32  : ns16650, no ERS, working fifo
com0: console
establish_irq
debug: unblock
wmtmr0 at obio0 addr 0xd8100000-0xd810ffff intr 48 : VC System Timer
establish_irq
debug: unblock
rn_init: radix functions require max_keylen be set
boot device: <unknown>
root device:
debugいれてみた。icuのモジュールが呼ばれている。

ということで、読むのができたら書けるはず。

unblock, blockで読み書きをしてみたが、値が書けるところと書けないところがある。irq=32だとかけて、irq=0だと書けない。
そもそもirq=0って使っていないはず。

establish_irqでis->is_irqで表示させたらirq=3である。なんだこれ。

とにかく、何で書けないのか。

頭にきて、attachで0xd8140000から0xFFFFFFFFを128個ほど書いて直後に読んで書き込めているかどうか表示させてみた。

すると、0xd8140040からは0x7F7F7F7Fが16個(8ビットで64個)と書けている。

そういえば、Linuxでは
#define    ICDC0_ADDR      (__IC_BASE + 0x40)      /* dest_ctl_addr[0]  */
と書いてあったのを忘れていた。0xd8140040から8ビット刻みで64個なので辻褄もあっている。ご丁寧に0で初期化されている。

つぎは、irq=3がirq=0になっているところ。

これは、block, unblockに渡されてくるirqbase, irq_maskの二つの合わせ技で考えなければならなかった。

これはsys/arch/arm/pic/pic.c#660を読むとわかる。
    660     (*pic->pic_ops->pic_establish_irq)(pic, is);
    661
    662     (*pic->pic_ops->pic_unblock_irqs)(pic, is->is_irq & ~0x1f,
    663         __BIT(is->is_irq & 0x1f));
establish_irqにはすなおにisが渡されているが、unblockには0x1fでビットがクリアされたものがirqbaseに渡されている。
0から31を表現する下位5ビット分(0x1f)を数字として、32ビットのビット位置で表現されている。

たとえば、irq=3であれば、0x1fでビットをクリアすると0x0なのでirqbaseはゼロ。下位5ビット分は3なので3ビット目が立っている0x8となる。3ビット目といっても0ビット目があるので1<<4になる。1を4ビットシフトさせて0x8である。

ということで、IRQ番号を求めるには、irqbase + (irq_maskの何ビット目が立っているか)を計算する必要がある。

geminiのようにIRQのmaskをビットでやるようなタイプだとこちらのほうが便利ということですね。

さて、IRQは3だということがわかったのですが、このIRQは使われていない(unusedで定義されている)はずなので、やっぱり何かが変です。

また、このestablishを読んでいるのはおそらくタイマードライバです。タイマードライバはirq=48でconfigに書いてあるのですが。

謎だ。

と思ったら、intrが3になる件、当たり前だった。
clock_ih = wm8750_intr_establish(WM8750_INT_TIMER3, IPL_CLOCK,
などとRPIのそのまま(RPIからWM8750に単純置換したまま)になっていたからだ。ばかすぎる。

ところでIPL_CLOCKのIPLとはなにか、Interreput Priority Levelとのこと。

sys/arch/evbarm/include/intr.h#44によると次のとおり。
     43 /* Interrupt priority "levels". */
     44 #define    IPL_NONE    0        /* nothing */
     45 #define    IPL_SOFTCLOCK    1        /* clock */
     46 #define    IPL_SOFTBIO    2        /* block I/O */
     47 #define    IPL_SOFTNET    3        /* software network interrupt */
     48 #define    IPL_SOFTSERIAL    4        /* software serial interrupt */
     49 #define    IPL_VM        5        /* memory allocation */
     50 #define    IPL_SCHED    6        /* clock interrupt */
     51 #define    IPL_HIGH    7        /* everything */
     52
     53 #define    NIPL        8
こういうレベルに基づいて割り込みを格付けしているのですね。

wm8750tmr_softcにint sc_intrというメンバを加え、attach時にobioから
        sc->sc_intr = obio->obio_intr;
てな感じでsoftcに保存。establish時にsc->sc_intrを使うようにすると、
com0 at obio0 addr 0xd8200000-0xd820ffff intr 32  : ns16650, no ERS, working fifo
com0: console
icu: establish_irq: is->is_irq=0x20
icu: unblock: irqbase=0x00000020, irqmask=0x00000001, 0x00000000 -> 0x00000008
wmtmr0 at obio0 addr 0xd8100000-0xd810ffff intr 48 : VC System Timer
icu: establish_irq: is->is_irq=0x30
icu: unblock: irqbase=0x00000020, irqmask=0x00010000, 0x00000008 -> 0x00000008
rn_init: radix functions require max_keylen be set
boot device: <unknown>
root device:
てな具合。irqmaskも0x10000なので、右から数えて17番目、0から始めて16を表現しているから、0x20+0x10=0x30であってますね。
IRQ = iobase + log(irqmask, 2) という数式で表せばいいかな。

ここまでのログを張っておこう。
WMT # go 8000
## Starting application at 0x00008000 ...
00008328
NetBSD
00000000 00000000 0049096b 00000412
00000000 00000412 00000004 00000412
c0000000 00000000 0049096b 0000041e
00003000 0000041e 00000004 0000041e
fe000000 d8000000 010fffff 00000412
00003f80 d8000412 00000010 00000412
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000



NetBSD/evbarm (APC) booting ...
initarm: Configuring system ...
arm32_bootmem_init: memstart=0, memsize=0x20000000, kernelstart=0x8000
arm32_bootmem_init: kernelend=0x291000
arm32_bootmem_init: adding 130415 free pages: [0x291000..0x1fffffff] (VA 0xc0291000)
arm32_bootmem_init: adding 8 free pages: [0..0x7fff] (VA 0xc0000000)
arm32_kernel_vm_init: 1 L2 pages are needed to map 0x2bc000 kernel bytes
arm32_kernel_vm_init: allocating page tables for vectoradd_pages: adding pv 0xc027fbe8 (pa 0x291000, va 0xc0291000, 1 pages) at tail
 kerneladd_pages: appending pv 0xc027fe70 (0x292000..0x292fff) to 0x291000..0x291fff
 vmadd_pages: appending pv 0xc027fe84 (0x293000..0x293fff) to 0x291000..0x292fff
add_pages: appending pv 0xc028892c (0x294000..0x297fff) to 0x291000..0x293fff
add_pages: appending pv 0xc027fe98 (0x298000..0x298fff) to 0x291000..0x297fff
add_pages: appending pv 0xc027feac (0x299000..0x299fff) to 0x291000..0x298fff
add_pages: appending pv 0xc027fec0 (0x29a000..0x29afff) to 0x291000..0x299fff
add_pages: appending pv 0xc027fed4 (0x29b000..0x29bfff) to 0x291000..0x29afff
add_pages: appending pv 0xc027fee8 (0x29c000..0x29cfff) to 0x291000..0x29bfff
add_pages: appending pv 0xc027fefc (0x29d000..0x29dfff) to 0x291000..0x29cfff
add_pages: appending pv 0xc027ff10 (0x29e000..0x29efff) to 0x291000..0x29dfff
add_pages: appending pv 0xc028016c (0x29f000..0x29ffff) to 0x291000..0x29efff
add_pages: appending pv 0xc0280180 (0x2a0000..0x2a0fff) to 0x291000..0x29ffff
add_pages: appending pv 0xc0280194 (0x2a1000..0x2a1fff) to 0x291000..0x2a0fff
add_pages: appending pv 0xc02801a8 (0x2a2000..0x2a2fff) to 0x291000..0x2a1fff
add_pages: appending pv 0xc02801bc (0x2a3000..0x2a4fff) to 0x291000..0x2a2fff
add_pages: appending pv 0xc0280158 (0x2a5000..0x2a6fff) to 0x291000..0x2a4fff
add_pages: appending pv 0xc027fc64 (0x2a7000..0x2aafff) to 0x291000..0x2a6fff
Creating L1 page table at 0x00294000
arm32_kernel_vm_init: adding L2 pt (VA 0xc0291000, PA 0x291000) for VA 0xffff0000
 (vectors)arm32_kernel_vm_init: adding L2 pt (VA 0xc0292000, PA 0x292000) for VA 0xc0000000 (kernel)
arm32_kernel_vm_init: adding L2 pt (VA 0xc0293000, PA 0x293000) for VA 0xc1000000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc0298000, PA 0x298000) for VA 0xc1400000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc0299000, PA 0x299000) for VA 0xc1800000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc029a000, PA 0x29a000) for VA 0xc1c00000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc029b000, PA 0x29b000) for VA 0xc2000000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc029c000, PA 0x29c000) for VA 0xc2400000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc029d000, PA 0x29d000) for VA 0xc2800000 (vm)
arm32_kernel_vm_init: adding L2 pt (VA 0xc029e000, PA 0x29e000) for VA 0xc2c00000 (vm)
Mapping kernel
arm32_kernel_vm_init: adding chunk for kernel text 0x8000..0x1affff (VA 0xc0008000)
add_pages: adding pv 0xc027fbd4 (pa 0x8000, va 0xc0008000, 424 pages) before pa 0x291000
arm32_kernel_vm_init: adding chunk for kernel data/bss 0x1b0000..0x290fff (VA 0xc01b0000)
add_pages: appending pv 0xc027fc3c (0x1b0000..0x290fff) to 0x8000..0x1affff
add_pages: merging pv 0xc027fbe8 (0x291000..0x2aafff) to 0x8000..0x290fff
Listing Chunks
arm32_kernel_vm_init: pv 0xc027fbd4: chunk VA 0xc0008000..0xc02aafff (PA 0x8000, prot 3, cache 1)

Mapping Chunks
arm32_kernel_vm_init: mapping last chunk VA 0xc0008000..0xc02aafff (PA 0x8000, prot 3, cache 1)
pmap_map_chunk: pa=0x8000 va=0xc0008000 size=0x2a3000 resid=0x2a3000 prot=0x3 cache=1
PPPPPPPPLLLLLLLLLLLLLLLSLLLLLLLLLLPPPPPPPPPPP
devmap: d8000000 -> d8ffffff @ fe000000
pmap_map_chunk: pa=0xd8000000 va=0xfe000000 size=0x1000000 resid=0x1000000 prot=0x3 cache=0
SSSSSSSSSSSSSSSS
                             Physical              Virtual        Num
                       Starting    Ending    Starting    Ending   Pages
               SDRAM: 0x00000000 0x1fffffff 0xc0000000 0xdfffffff 131072
        text section: 0x00008000 0x001affff 0xc0008000 0xc01affff 424
        data section: 0x001c0000 0x0027f4c0 0xc01c0000 0xc027f4c0 192
         bss section: 0x0027f4c0 0x0029096c 0xc027f4c0 0xc029096c 18
   L1 page directory: 0x00294000 0x00297fff 0xc0294000 0xc0297fff 4
   ABT stack (CPU 0): 0x0029f000 0x0029ffff 0xc029f000 0xc029ffff 1
   FIQ stack (CPU 0): 0x002a0000 0x002a0fff 0xc02a0000 0xc02a0fff 1
   IRQ stack (CPU 0): 0x002a1000 0x002a1fff 0xc02a1000 0xc02a1fff 1
   UND stack (CPU 0): 0x002a2000 0x002a2fff 0xc02a2000 0xc02a2fff 1
  IDLE stack (CPU 0): 0x002a3000 0x002a4fff 0xc02a3000 0xc02a4fff 2
           SVC stack: 0x002a5000 0x002a6fff 0xc02a5000 0xc02a6fff 2
      Message Buffer: 0x002a7000 0x002aafff 0xc02a7000 0xc02aafff 4
   Exception Vectors: 0x002ab000 0x002abfff 0xffff0000 0xffff0fff 1
         Free Memory: 0x002ac000 0x1fffffff                       130388
         Free Memory: 0x00000000 0x00007fff                       8
switching to new L1 page table @0x294000...TTBR0=0x294000 OK
done.
nfreeblocks = 2, free_pages = 130396 (0x1fd5c)
bootstrap done.
vectors 0xffff0000
init subsystems: stacks vectors undefined page pmap_physload pmap [ Kernel symbol table missing! ]
done.
Loaded initial symtab at 0xc01c4364, strtab at 0xc01e34d4, # entries 7944
pmap_postinit: Allocated 35 static L1 descriptor tables
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 6.99.23 (APC) #55: Mon Sep  9 22:46:37 UTC 2013
        root@builder.localdomain:/usr/obj/sys/arch/evbarm/compile/APC
total memory = 512 MB
avail memory = 499 MB
mainbus0 (root)
cpu0 at mainbus0 core 0: ARM1176JZ-S r0p7 (ARM11J V6ZK core)
cpu0: DC enabled IC enabled WB enabled LABT
cpu0: 16KB/32B 4-way L1 Instruction cache
cpu0: 16KB/32B 4-way write-back-locking-C L1 Data cache
vfp0 at cpu0: VFP11
obio0 at mainbus0
<wm8750_uart_match>
comprobe1 0
</wm8750_uart_match rv=0>
wmicu0 at obio0 addr 0xd8140000-0xd814ffff
icu-debug: d8140040: 00000000
icu-debug: d8140044: 00000000
icu-debug: d8140048: 00000000
icu-debug: d814004c: 00000000
icu-debug: d8140050: 00000000
icu-debug: d8140054: 00000000
icu-debug: d8140058: 00000000
icu-debug: d814005c: 00000000
icu-debug: d8140060: 00000000
icu-debug: d8140064: 00000000
icu-debug: d8140068: 00000000
icu-debug: d814006c: 00000000
icu-debug: d8140070: 00000000
icu-debug: d8140074: 00000000
icu-debug: d8140078: 00000000
icu-debug: d814007c: 00000000
<wm8750_uart_match>
com0 at obio0 addr 0xd8200000-0xd820ffff intr 32  : ns16650, no ERS, working fifo
com0: console
icu: establish_irq: is->is_irq=0x20
icu: unblock: irqbase=0x00000020, irqmask=0x00000001, 0x00000000 -> 0x00000008
wmtmr0 at obio0 addr 0xd8100000-0xd810ffff intr 48 : VC System Timer
icu: establish_irq: is->is_irq=0x30
icu: unblock: irqbase=0x00000020, irqmask=0x00010000, 0x00000008 -> 0x00000008
rn_init: radix functions require max_keylen be set
boot device: <unknown>
root device:

名前:  非公開コメント   

  • TB-URL  http://www.tokuda.net/diary/adiary.cgi/0831/tb/