動きはじめると、まだ辛い。ぶりかえしてしまったかも。健康って素晴しい。
ちょっとNetBSD/sh3について徒然に。
実際のところは最初のページのstruct user(今はpcb)の後までカーネルスタック として使えるのだけど、そこはなしということになる。
なんでこれがあるかというと、SH3の場合はH/Wでワイヤードエントリを作れな いので、割込まれた時にカーネルスタックをアクセスしてさらにフォルトして しまうのを避けるために、その場で直接カーネルスタックをTLBに載せるという 方法をとった。そのトリッキーな動作のデバッグ用。実際のところ、割込みが きつくなると4KBではカーネルスタックが足りなくなる。
NetBSD/sh3の実装は最初から__SWAP_BROKEN、つまりu-areaはスワップアウトし ない。これはなんでこうしたかというと、u-areaの中のポインタをu-areaに持っ ていると、それをスワップアウト/インされた時にリマップしないといけないの が面倒だからだ。
今回u-areaのスワップが廃止された。カーネル側でそれを廃止したため、 u-areaは匿名領域からとるのではなく、uvm_km.cあたりのカーネル領域のプー ルからとることになった(スワップアウトする必要が一切なくなったので)。カー ネル領域はページアウトされない。
匿名領域の確保の場合、保護のために(ユーザにも使われるので)ページをゼロ クリアするのだけど、カーネル領域はそれは必要ないのでゼロクリアされない。 ということでゼロクリアを期待していたコードが動かなくなってしまった。 pcb_onfaultにゴミが入っていたりすると、TLBミスした時におかしい挙動になっ てしまう。
昔からu-areaはゼロにしないという設定だったのだけど、いろいろな設定の関 係でたまたまゼロになっていた。(もしかするとたまにゼロじゃない時もあった のかも)
ちょっと後半あやふや。
ちょっとNetBSD/sh3について徒然に。
sh3/param.h #define UPAGES 3 /* pages of u-area */ #define USPACE (UPAGES * NBPG) /* total size of u-area */ #if UPAGES == 1 #error "too small u-area" #elif UPAGES == 2 #define P1_STACK /* kernel stack is P1-area */ #else #undef P1_STACK /* kernel stack is P3-area */ #endifUPAGESが2の場合、カーネルスタックは1ページのみで連続領域なのでスタック ポインタをP1で持てる。しかし、UPAGESが3以上の場合、そのカーネルスタック 2ページはP3では連続していてもP1では必ずしも連続しないので、スタックポイ ンタはP3で持たないといけない。
実際のところは最初のページのstruct user(今はpcb)の後までカーネルスタック として使えるのだけど、そこはなしということになる。
なんでこれがあるかというと、SH3の場合はH/Wでワイヤードエントリを作れな いので、割込まれた時にカーネルスタックをアクセスしてさらにフォルトして しまうのを避けるために、その場で直接カーネルスタックをTLBに載せるという 方法をとった。そのトリッキーな動作のデバッグ用。実際のところ、割込みが きつくなると4KBではカーネルスタックが足りなくなる。
NetBSD/sh3の実装は最初から__SWAP_BROKEN、つまりu-areaはスワップアウトし ない。これはなんでこうしたかというと、u-areaの中のポインタをu-areaに持っ ていると、それをスワップアウト/インされた時にリマップしないといけないの が面倒だからだ。
今回u-areaのスワップが廃止された。カーネル側でそれを廃止したため、 u-areaは匿名領域からとるのではなく、uvm_km.cあたりのカーネル領域のプー ルからとることになった(スワップアウトする必要が一切なくなったので)。カー ネル領域はページアウトされない。
匿名領域の確保の場合、保護のために(ユーザにも使われるので)ページをゼロ クリアするのだけど、カーネル領域はそれは必要ないのでゼロクリアされない。 ということでゼロクリアを期待していたコードが動かなくなってしまった。 pcb_onfaultにゴミが入っていたりすると、TLBミスした時におかしい挙動になっ てしまう。
昔からu-areaはゼロにしないという設定だったのだけど、いろいろな設定の関 係でたまたまゼロになっていた。(もしかするとたまにゼロじゃない時もあった のかも)
ちょっと後半あやふや。
昔のカーネル cpu0 at mainbus0: SH4A 599.999 MHz PCLOCK 49.999 MHz cpu0: 32KB/32B 4-way set-associative Instruction cache. cpu0: 32KB/32B 4-way set-associative Data cache. cpu0: U0, P0, P3 write-back; P1 write-back cpu0: full-associative 4 ITLB, 64 UTLB entries cpu0: multiple virtual storage mode, SQ access: kernel, wired 7 cpu0: 32bit physical address mode. TLB-compatible mode. VPN:80000000 (V) PPN:0 (V) 512MB, bufferd write, cacheable, write-back, VPN:a0000000 (V) PPN:0 (V) 512MB, bufferd write, uncacheable, write-back, shb0 at mainbus0 scif0 at shb0 scif0: console PCB0xc1820000=>5ffde000 ←u-areaはanonからもってきている。これはゼロクリア PCB0xc1823000=>5ffdb000 PCB0xc1826000=>5ffd8000 PCB0xc1829000=>5ffd5000 PCB0xc182c000=>5ffd2000 PCB0xc182f000=>5ffcf000 PCB0xc1832000=>5ffcc000 PCB0xc1835000=>5ffc9000 pmap_prefer 1 PCB0xc1832000=>5ffcc000 rn_init: radix functions require max_keylen be set PCB0xc1835000=>5ffc9000 root on md0a dumps on md0b mountroot: trying ffs... root file system type: ffs
今のカーネル cpu0: 32bit physical address mode. TLB-compatible mode. VPN:80000000 (V) PPN:0 (V) 512MB, bufferd write, cacheable, write-back, VPN:a0000000 (V) PPN:0 (V) 512MB, bufferd write, uncacheable, write-back, shb0 at mainbus0 scif0 at shb0 scif0: console PCB(new)0xc2262000=>febc000 ←u-areaはカーネルのプールページから持ってきている。 PCB(new)0xc2265000=>feb9000 PCB(new)0xc2268000=>feb6000 PCB(new)0xc226b000=>feb3000 PCB(new)0xc226e000=>feb0000 PCB(new)0xc2271000=>feac000 PCB(new)0xc2274000=>fea9000 PCB(new)0xc2277000=>fea6000 pmap_prefer 1 pmap_growkernel: fe93000 for 9 pmap_growkernel: fe92000 for 10 PCB(new)0xc2274000=>fea9000 rn_init: radix functions require max_keylen be set PCB(new)0xc2277000=>fea6000 root on md0a dumps on md0b mountroot: trying ffs... root file system type: ffs WARNING: no TOD clock present WARNING: using filesystem time WARNING: CHECK AND RESET THE DATE! PCB(new)0xc2271000=>feac000 PCB(new)0xc226e000=>feb0000 PCB(new)0xc226b000=>feb3000 PCB(new)0xc2268000=>feb6000 __pmap_asid_alloc: 1 init: copying out flags `-s' 3プロセスの起動について。
init: copying out flags `-s' 3 ここで新しくプロセスを作ってそれがASID1になった。 tlb_exception: ASID1 まずはスタックをアクセスしてフォルト。ここで失敗するのはこの領域の ページテーブルページもないから。 FAILED __pmap_pte_load ASID=1 va=7fffeffd ここでuvm_faultして、ページテーブルページを割当てて、その中の該当ページ をマップする。pcb_onfaultにゴミが入っていると、ここまでに来ずにページテー ブルにないというところでそのままリターンしてしまうのでAbort trapしてし まう。 ------------------------------START uvm_fault_internal start=7fffeffd 0x8900b978 pmap_enter pa=5ffc6000 va=7fffe000 0x8909aa8a __pmap_pte_alloc 7fffe000 ------------------------------END ここではじめて触ったスタックがロードされる。ここまでで一回の例外処理。 __pmap_pte_load ASID=1 va=7fffeffd init: copying out path `/sbin/init' 11
