xv6-rev6 読み (11)
何故に 0x10000 なのか、な謎に現実トウヒ。
とりあえず Makefile から、ということで xv6.img のルールが以下。
xv6.img: bootblock kernel fs.img dd if=/dev/zero of=xv6.img count=10000 dd if=bootblock of=xv6.img conv=notrunc dd if=kernel of=xv6.img seek=1 conv=notrunc
先頭セクタに bootblock がいて、以降に kernel が、ということなはず。bootblock のルールが以下。
bootblock: bootasm.S bootmain.c $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o $(OBJDUMP) -S bootblock.o > bootblock.asm $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock ./sign.pl bootblock
start がエントリポイントで 0x7c00 番地がテキストセグメントの先頭らしい。あと、sign.pl 使ってマジックナンバーを末端に書きだしているはず。また、kernel のルールが以下。
kernel: $(OBJS) entry.o entryother initcode kernel.ld $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother $(OBJDUMP) -S kernel > kernel.asm $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym
エントリポイントは initcode らしくルールが以下。
initcode: initcode.S $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o $(OBJCOPY) -S -O binary initcode.out initcode $(OBJDUMP) -S initcode.o > initcode.asm
start がエントリポイントで 0 番地が開始位置らしい。
あと kernel.ld の先頭部分を以下に引用。
ENTRY(_start) SECTIONS { /* Link the kernel at this address: "." means the current address */ /* Must be equal to KERNLINK */ . = 0x80100000; .text : AT(0x100000) { *(.text .stub .text.* .gnu.linkonce.t.*) }
xv6 では objdump 使って *.asm という非常に参考になるアウトプットが出力されるんですが、例えば bootblock.asm の先頭部分が以下になってます。
bootblock.o: file format elf32-i386 Disassembly of section .text: 00007c00 <start>: # with %cs=0 %ip=7c00. .code16 # Assemble for 16-bit mode .globl start start: cli # BIOS enabled interrupts; disable 7c00: fa cli
start から開始で 0x7c00 になってます。あるいは kernel.asm の先頭部分は以下。
kernel: file format elf32-i386 Disassembly of section .text: 80100000 <multiboot_header>: 80100000: 02 b0 ad 1b 00 00 add 0x1bad(%eax),%dh 80100006: 00 00 add %al,(%eax) 80100008: fe 4f 52 decb 0x52(%edi) 8010000b: e4 0f in $0xf,%al 8010000c <entry>: # Entering xv6 on boot processor, with paging off. .globl entry entry: # Turn on page size extension for 4Mbyte pages movl %cr4, %eax 8010000c: 0f 20 e0 mov %cr4,%eax
ソース (entry.S) の上記な定義部分は以下になってまして
.globl _start _start = V2P_WO(entry) # Entering xv6 on boot processor, with paging off. .globl entry entry: # Turn on page size extension for 4Mbyte pages movl %cr4, %eax
ちょっとこのあたり詳細不明。で、真のエントリポイントである 0x7c00 な定義は bootasm.S で定義されていて protected mode に移行して bootmain という手続きに jump します。bootmain 手続きでは 0x10000 番地から elf ヘッダを読み込んで、ということをしている模様。
void bootmain(void) { struct elfhdr *elf; struct proghdr *ph, *eph; void (*entry)(void); uchar* pa; elf = (struct elfhdr*)0x10000; // scratch space // Read 1st page off disk readseg((uchar*)elf, 4096, 0);
で、諸々のチェックをした後に jump してます。
// Call the entry point from the ELF header. // Does not return! entry = (void(*)(void))(elf->entry); entry();
この 0x10000 が課題。xv6 なディレクトリ配下には根拠は皆無。