# HG changeset patch
# User tobaru
# Date 1523959635 -32400
# Node ID fae2e3cb58213665acc123ed16baabdc6ceb68b9
xv6_read
diff -r 000000000000 -r fae2e3cb5821 Xv6_read_0416.pdf
Binary file Xv6_read_0416.pdf has changed
diff -r 000000000000 -r fae2e3cb5821 Xv6読み会.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Xv6読み会.html Tue Apr 17 19:07:15 2018 +0900
@@ -0,0 +1,665 @@
+
+
+
+
+
+
+
+X.v6読み会
+
+
+
+
+
+
+
+
+
+X.v6読み会
+
+Boot Sequence
+
+Boot
+
+ Kernel load
+ Page Table (Boot用のPagetableの設定)
+ initialize (memory / IO / process / file )
+ ini process
+
+
+
+
+
+
+ls 時の User と System
+
+User Sys
+fork
+exec ls (lsを探す)
+ open ls
+ load ls
+ (loadの後にmemory空間の初期化を行う)
+ pase table reset
+ goto User Mode
+opendir
+ system call (file IO) (VM)
+ (filesystemを読んでまたUserに値を返す)
+
+
+
+
+
+10行目 VM の説明
+
+
+lsは自分で仮装メモリにアクセスしていくので memory allocation をやる
+malloc は User library だが memory の要求は System でやらなきゃいけない
+break とい System call で memory を増やす
+memory を増やすと OS は最初に ls のバイナリを生成
+すると、break で取った領域が別にできる
+breakで 取った memory が全部 リアル memory に割り当てられるわけではない
+いくつかは仮想メモリに行く
+memory にアクセスした時に仮装メモリだったらtrapしてmemoryを割り当てる
+memoryが割り当てられなければ、他の実メモリを追い出して書き換える
+VM関係の一連の処理がある
+
+fork
+
+
+forkすると process structure ができる
+process自体は active や waitの状態を持っている
+複数のactiveがあると順に実行していく(scheduler)
+
+kernel の要素
+
+
+process manegement
+scheduler
+file IO
+Virtual Memory
+
+
+
+この4つの Kernel の要素を読んでいく
+
+X.v6 の trace
+
+arm 用の gdb で kernel.elf を開く
+
+dalmoreに入って
+
+cd /mnt/dalmore-home/one/src/xv6-rpi/src
+/net/open/Linux/arm/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi-gdb kernel.elf
+
+qemuを立ち上げる
+見たいのは Boot Sequence だから qemu-debug を使う
+
+make clean; make -f makefile-armclang qemu-debug
+
+makefile-armclang の qemu-debug 部分
+
+qemu-debug : kernel.elf
+ @clear
+ @echo "Press Ctrl-A and then X to terminate QEMU session\n"
+ export QEMU_AUDIO_DRV=none ; $(QEMU) -M versatilepb -m 128 -cpu ${QEMUCPU} -nographic -singlestep -d exec,cpu,guest_errors -D qemu.log -kernel kernel.elf -s -S
+
+
+-M versatilepb
+
+
+仮想メモリにこの firmwere を使うという指示
+versarilepb は Raspi(ARM) のfirmwereの一種
+
+ -m 128
+
+
+-cpu ${QEMUCPU}
+
+
+cpu の種類
+アーキテクチャによって命令違う
+armのxv6を作る時のcompile時にcpuに教えるcpuの種類と合わせる必要がある
+名前がqemu側とcompile側のcpuの名前が違うので試行錯誤して合わせる
+
+-s -S
+
+
+ Boot時に debugger が接続するまで止めるようにする
+
+
+
+gdb
+
+(gdb)b _start
+
+# remote 接続
+(gdb)target remote :1234
+
+# bt: stackを参照して、stack上のfanction callの履歴を調べる
+(gdb)bt
+
+(gdb)info registarts (初期のレジスタ)
+r0 ~ r12 (ARMのレジスタは0~12)
+sp (stack pointer)
+lr (link regester)
+pc (program counter)
+cpsr (cpu statusのレジスタ)
+
+(gdb)disass
+# disassemblerの略
+
+(gdb)x/20x $pc+48+4
+0x100030
+# entry.Sのr1,=edata_entryやend_entryが$pc+48に変わってる
+# pcは次の命令を指している10030->10038だから48からさらに+4
+
+(gdb)p (void*) edata_entry
+$1 = (void *0) 0x10588 <edata_entry>
+# 10588がレジスタのr1に入る
+
+(gdb)stepi
+(gdb)info registers
+r1 0x10588 66952
+
+(gdb)stepi
+(gdb)info registers
+r1 0x10588 66952
+r2 0x19000 102400
+
+(gdb)define ni
+>x/1i $pc
+>x/1i $pc
+>end
+# こうするとentry.Sを1命令ずつ実行できる
+
+
+(gdb)si
+0x0001000c in _start ()
+=> 0x1000c <_start+12>: cmp r1,r2
+
+(gdb)si
+0x0001000c in _start ()
+=> 0x1014c <_start+16>: cmp r1,{r3}
+
+(gdb)disass
+=> 0x00010014 <*20>: blt
+ 0x00010018 <*24>: msr
+# blt でループしてることがわかる
+
+(gdb)tb *0x00010018
+(gdb)c
+# bltのループを抜ける
+
+(gdb)disass
+(gbd)info registers
+r1 0x19000 102400
+r2 0x19000 102400
+# r2の値になるまでr1をincrementすることでループを抜けてる事がわかる
+# 19000までmemoryがある
+
+# CPUのコントロール
+
+
+(gdb)si
+(gdb)info registers
+cpsr 0x600001d3
+
+# entry.Sの MSRの行を実行
+(gdb)si
+(gdb)info registers
+cpsr 0xd3
+# CPUのコントロールレジスタを指定している
+# supervisorじゃないとアクセスできない
+
+# entry.Sの LDR の行を実行
+(gdb) si
+(gdb) info registers
+sp 0x12000
+# 0x0 -> 0x12000
+# stack ponterが設定されたのでサブルーチンコールが使えるようになる
+# サブルーチンコール 戻り先をstackに覚えておいてそこに飛ぶ
+# lr(link register)に覚えさせる事で1回だけアクセスせずに飛ぶ事ができる
+# BL breach & link
+
+
+(gdb)si
+(gdb)info registers
+lr 0x10024
+
+(gdb)disass _start
+ 0x00010024 <+36>: b
+
+# startまできたのでここ以降はstart.c
+(gdb)l
+# cなので next が使える
+
+(gdb)next
+(gdb)next
+(gdb)s
+set_bootpgtbl(... lent=1048576 ...)
+(gdb)p (void*) len
+$2 = (void *) 0x100000
+# 1048576 は16進数で100000
+
+(gdb)disass
+
+
+
+
+entry.S
+
+_start:
+ LDR r1, =edata_entry
+ LDR r2, =end_entry
+ MOV r3, #0x00
+
+# BLT までをループ
+1:
+ CMP r1, r2
+ STMLTIA r1!, {r3} # {}はレジスタのリスト r1にセーブする
+ # !は セーブした数だけr1を進める(++とかと一緒)
+ # Memclear とかと一緒
+
+ BLT 1b
+
+
+ # initialize stack pointers for svc modes
+ # CPUのコントロールレジスタを指定
+ # cpsr 0xd3
+ MSR CPSR_cxsf, #(SVC_MODE|NO_INT)
+ LDR sp, =svc_stktop
+
+ BL start
+ B .
+
+
+B . まで行くとそこを永遠とループする
+
+
+ARM fault持ってるので Bではなくfaultにすべき
+
+
+
+start.c
+
+l.166~
+
+void start (void)
+{
+ uint32 vectbl;
+ _puts("starting xv6 for ARM...\n");
+
+ // double map the low memory, required to enable paging
+ // we do not map all the physical memory
+ set_bootpgtbl(0, 0, INIT_KERNMAP, 0);
+ set_bootpgtbl(KERNBASE, 0, INIT_KERNMAP, 0);
+
+l.69~
+
+ for (idx = 0; idx < len; idx++) {
+ pde = (phy << PDE_SHIFT);
+
+ if (!dev_mem) {
+ // normal memory, make it kernel-only, cachable, bufferable
+ pde |= (AP_KO << 10) | PE_CACHE | PE_BUF | KPDE_TYPE;
+ // |(or) を使って足して行く
+ } else {
+ // device memory, make it non-cachable and non-bufferable
+ pde |= (AP_KO << 10) | KPDE_TYPE;
+ }
+
+
+ARMv6 page table entry
+https://developer.arm.com/docs/ddi0211/h/memory-management-unit/hardware-page-table-translation/armv6-page-table-translation-subpage-ap-bits-disabled
+
+
+
+
+
+
+
+
diff -r 000000000000 -r fae2e3cb5821 Xv6読み会.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Xv6読み会.md Tue Apr 17 19:07:15 2018 +0900
@@ -0,0 +1,302 @@
+# X.v6読み会
+
+## Boot Sequence
+
+ **Boot**
+
+ ```
+ Kernel load
+ Page Table (Boot用のPagetableの設定)
+ initialize (memory / IO / process / file )
+ ini process
+
+ ```
+ ![](./xv6_BootSequence.svg)
+
+
+- Kernel load
+ - x86ならEFIがある
+ - ARMだとVersatile(firmware)
+
+
+- paging を設定しなければ動かない
+- Boot用のpagetableの設定ができた後一連の初期化を行う
+ - memory
+ - I/O
+ - process
+ - file
+- 初期化が終わった後
+ - init process(process番号1番)
+ - init process は linux だと rc.d/~ の下にある
+
+## ls 時の User と System
+```
+User Sys
+fork
+exec ls (lsを探す)
+ open ls
+ load ls
+ (loadの後にmemory空間の初期化を行う)
+ pase table reset
+ goto User Mode
+opendir
+ system call (file IO) (VM)
+ (filesystemを読んでまたUserに値を返す)
+
+
+
+```
+
+- 10行目 **VM** の説明
+ - lsは自分で仮装メモリにアクセスしていくので memory allocation をやる
+ - malloc は User library だが memory の要求は System でやらなきゃいけない
+ - break とい System call で memory を増やす
+ - memory を増やすと OS は最初に ls のバイナリを生成
+ - すると、break で取った領域が別にできる
+ - breakで 取った memory が全部 リアル memory に割り当てられるわけではない
+ - いくつかは仮想メモリに行く
+ - memory にアクセスした時に仮装メモリだったらtrapしてmemoryを割り当てる
+ - memoryが割り当てられなければ、他の実メモリを追い出して書き換える
+ - VM関係の一連の処理がある
+
+- fork
+ - forkすると process structure ができる
+ - process自体は active や waitの状態を持っている
+ - 複数のactiveがあると順に実行していく(scheduler)
+
+
+- kernel の要素
+ - process manegement
+ - scheduler
+ - file IO
+ - Virtual Memory
+
+この4つの Kernel の要素を読んでいく
+
+## X.v6 の trace
+arm 用の gdb で kernel.elf を開く
+
+dalmoreに入って
+
+```
+cd /mnt/dalmore-home/one/src/xv6-rpi/src
+/net/open/Linux/arm/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi-gdb kernel.elf
+```
+
+qemuを立ち上げる
+見たいのは Boot Sequence だから qemu-debug を使う
+
+```
+make clean; make -f makefile-armclang qemu-debug
+```
+
+### makefile-armclang の qemu-debug 部分
+
+```
+qemu-debug : kernel.elf
+ @clear
+ @echo "Press Ctrl-A and then X to terminate QEMU session\n"
+ export QEMU_AUDIO_DRV=none ; $(QEMU) -M versatilepb -m 128 -cpu ${QEMUCPU} -nographic -singlestep -d exec,cpu,guest_errors -D qemu.log -kernel kernel.elf -s -S
+```
+- -M versatilepb
+ - 仮想メモリにこの firmwere を使うという指示
+ - versarilepb は Raspi(ARM) のfirmwereの一種
+- -m 128
+ - memory の量
+- -cpu ${QEMUCPU}
+ - cpu の種類
+ - アーキテクチャによって命令違う
+ - armのxv6を作る時のcompile時にcpuに教えるcpuの種類と合わせる必要がある
+ - 名前がqemu側とcompile側のcpuの名前が違うので試行錯誤して合わせる
+- -s -S
+ - Boot時に debugger が接続するまで止めるようにする
+
+### gdb
+
+```
+(gdb)b _start
+
+# remote 接続
+(gdb)target remote :1234
+
+# bt: stackを参照して、stack上のfanction callの履歴を調べる
+(gdb)bt
+
+(gdb)info registarts (初期のレジスタ)
+r0 ~ r12 (ARMのレジスタは0~12)
+sp (stack pointer)
+lr (link regester)
+pc (program counter)
+cpsr (cpu statusのレジスタ)
+
+(gdb)disass
+# disassemblerの略
+
+(gdb)x/20x $pc+48+4
+0x100030
+# entry.Sのr1,=edata_entryやend_entryが$pc+48に変わってる
+# pcは次の命令を指している10030->10038だから48からさらに+4
+
+(gdb)p (void*) edata_entry
+$1 = (void *0) 0x10588
+# 10588がレジスタのr1に入る
+
+(gdb)stepi
+(gdb)info registers
+r1 0x10588 66952
+
+(gdb)stepi
+(gdb)info registers
+r1 0x10588 66952
+r2 0x19000 102400
+
+(gdb)define ni
+>x/1i $pc
+>x/1i $pc
+>end
+# こうするとentry.Sを1命令ずつ実行できる
+
+
+(gdb)si
+0x0001000c in _start ()
+=> 0x1000c <_start+12>: cmp r1,r2
+
+(gdb)si
+0x0001000c in _start ()
+=> 0x1014c <_start+16>: cmp r1,{r3}
+
+(gdb)disass
+=> 0x00010014 <*20>: blt
+ 0x00010018 <*24>: msr
+# blt でループしてることがわかる
+
+(gdb)tb *0x00010018
+(gdb)c
+# bltのループを抜ける
+
+(gdb)disass
+(gbd)info registers
+r1 0x19000 102400
+r2 0x19000 102400
+# r2の値になるまでr1をincrementすることでループを抜けてる事がわかる
+# 19000までmemoryがある
+
+# CPUのコントロール
+
+
+(gdb)si
+(gdb)info registers
+cpsr 0x600001d3
+
+# entry.Sの MSRの行を実行
+(gdb)si
+(gdb)info registers
+cpsr 0xd3
+# CPUのコントロールレジスタを指定している
+# supervisorじゃないとアクセスできない
+
+# entry.Sの LDR の行を実行
+(gdb) si
+(gdb) info registers
+sp 0x12000
+# 0x0 -> 0x12000
+# stack ponterが設定されたのでサブルーチンコールが使えるようになる
+# サブルーチンコール 戻り先をstackに覚えておいてそこに飛ぶ
+# lr(link register)に覚えさせる事で1回だけアクセスせずに飛ぶ事ができる
+# BL breach & link
+
+
+(gdb)si
+(gdb)info registers
+lr 0x10024
+
+(gdb)disass _start
+ 0x00010024 <+36>: b
+
+# startまできたのでここ以降はstart.c
+(gdb)l
+# cなので next が使える
+
+(gdb)next
+(gdb)next
+(gdb)s
+set_bootpgtbl(... lent=1048576 ...)
+(gdb)p (void*) len
+$2 = (void *) 0x100000
+# 1048576 は16進数で100000
+
+(gdb)disass
+
+```
+
+
+- memory に直接 load できる値は 長い値だとmemory一旦置かないといけない
+
+- 一番最初に呼び出すのは C で書かれたファイルじゃなくてアセンブラ
+ - entry.S で行なっている
+
+### entry.S
+
+```
+_start:
+ LDR r1, =edata_entry
+ LDR r2, =end_entry
+ MOV r3, #0x00
+
+# BLT までをループ
+1:
+ CMP r1, r2
+ STMLTIA r1!, {r3} # {}はレジスタのリスト r1にセーブする
+ # !は セーブした数だけr1を進める(++とかと一緒)
+ # Memclear とかと一緒
+
+ BLT 1b
+
+
+ # initialize stack pointers for svc modes
+ # CPUのコントロールレジスタを指定
+ # cpsr 0xd3
+ MSR CPSR_cxsf, #(SVC_MODE|NO_INT)
+ LDR sp, =svc_stktop
+
+ BL start
+ B .
+```
+
+- B . まで行くとそこを永遠とループする
+ - ARM fault持ってるので Bではなくfaultにすべき
+
+
+### start.c
+l.166~
+
+```
+void start (void)
+{
+ uint32 vectbl;
+ _puts("starting xv6 for ARM...\n");
+
+ // double map the low memory, required to enable paging
+ // we do not map all the physical memory
+ set_bootpgtbl(0, 0, INIT_KERNMAP, 0);
+ set_bootpgtbl(KERNBASE, 0, INIT_KERNMAP, 0);
+```
+
+l.69~
+
+```
+ for (idx = 0; idx < len; idx++) {
+ pde = (phy << PDE_SHIFT);
+
+ if (!dev_mem) {
+ // normal memory, make it kernel-only, cachable, bufferable
+ pde |= (AP_KO << 10) | PE_CACHE | PE_BUF | KPDE_TYPE;
+ // |(or) を使って足して行く
+ } else {
+ // device memory, make it non-cachable and non-bufferable
+ pde |= (AP_KO << 10) | KPDE_TYPE;
+ }
+```
+- ARMv6 page table entry
+https://developer.arm.com/docs/ddi0211/h/memory-management-unit/hardware-page-table-translation/armv6-page-table-translation-subpage-ap-bits-disabled
+
diff -r 000000000000 -r fae2e3cb5821 xv6_BootSequence.graffle
Binary file xv6_BootSequence.graffle has changed
diff -r 000000000000 -r fae2e3cb5821 xv6_BootSequence.pdf
Binary file xv6_BootSequence.pdf has changed
diff -r 000000000000 -r fae2e3cb5821 xv6_BootSequence.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xv6_BootSequence.svg Tue Apr 17 19:07:15 2018 +0900
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Produced by OmniGraffle 7.7.1
+ 2018-04-17 01:17:12 +0000
+
+
+ Canvas 1
+
+
+ Layer 1
+
+
+
+
+ CPU
+
+
+
+
+
+
+
+
+
+
+ paging
+
+
+
+
+
+
+ dev
+
+
+
+
+
+
+ MacBook Pro
+
+
+
+
+
+
+ Kernel
+
+
+
+
+
+
+ Memory
+
+
+
+
+ UART
+ ( VM
+ で動く
+ )
+
+
+
+
+ USB serial Interface
+
+
+
+
+ paging
+ のメカニズムを使って
+ メモリにアクセスする
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+