APC8750にNetBSD/evbarmを移植するための記録 9/7 その1
ずいぶん時間が過ぎ去った。割り込みコントローラの続き。
割り込みコントローラのアドレスをダンプしてみる
u-bootも見たほうがいいか?
うーん、探せない...
まぁ、触ってみるか。
bus_space_read_4の引き数の最後は割り込みコントローラの先頭アドレス(0xd8140000)からの相対位置でよい。最初は絶対アドレスで書いていたら
もちろん、先のコードでも
ということで、読むのができたら書けるはず。
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では
つぎは、irq=3がirq=0になっているところ。
これは、block, unblockに渡されてくるirqbase, irq_maskの二つの合わせ技で考えなければならなかった。
これはsys/arch/arm/pic/pic.c#660を読むとわかる。
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になる件、当たり前だった。
ところでIPL_CLOCKのIPLとはなにか、Interreput Priority Levelとのこと。
sys/arch/evbarm/include/intr.h#44によると次のとおり。
wm8750tmr_softcにint sc_intrというメンバを加え、attach時にobioから
IRQ = iobase + log(irqmask, 2) という数式で表せばいいかな。
ここまでのログを張っておこう。
割り込みコントローラのアドレスをダンプしてみる
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:
コメント(0件)
- TB-URL http://www.tokuda.net/diary/0831/tb/