Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BHyVeでOSvを起動したい
〜BIOSがなくてもこの先生きのこるには〜

Avatar for Takuya ASADA Takuya ASADA
December 08, 2013

 BHyVeでOSvを起動したい
〜BIOSがなくてもこの先生きのこるには〜

Avatar for Takuya ASADA

Takuya ASADA

December 08, 2013
Tweet

More Decks by Takuya ASADA

Other Decks in Technology

Transcript

  1. OSvͱ͸ʁ • Ծ૝Խ؀ڥ্ͰಛఆʢJavaʣΞϓϦέʔγϣϯΛޮ཰Α࣮͘ߦ͢ ΔࣄʹಛԽͨ͠OS • Cloudis Systems͕։ൃ
 KVMΛ։ൃͨ͠Qumranetͷϝϯόʔ
 Avi Kivity͕CTO

    • KVM, XenͰಈ͘ˠAmazon EC2΁σϓϩΠՄೳ • BSDϥΠηϯε • http://osv.io/ • https://github.com/cloudius-systems/osv
  2. #)Z7Fͱ͸ʁ w 'SFF#4%൛ͷ-JOVY,7.ͷΑ͏ͳ΋ͷ w ΧʔωϧଆυϥΠόɾϢʔβϥϯυϓϩάϥϜڞʹ'SFF#4%CBTFπϦʔ্Ͱ։ൃ ͞Ε͍ͯΔ w *OUFM75Λ༻͍ͨϋΠύʔόΠβ w ,7.ͱҟͳΓϢʔβϥϯυଆ

    w 'SFF#4%3&-&"4&Ͱಉࠝ w ήετ04ͱͯ͠'SFF#4% -JOVY 0QFO#4%͕ىಈ
 ʢୠ͠Y@൛ͷ04ͷΈʣ w IUUQCIZWFPSH w ৄ͘͠͸ࢲͷ4PGUXBSF%FTJHOͷ࿈ࡌΛಡΜͰԼ͍͞
  3. #*04Λ༻͍Δैདྷͷϒʔτϓ ϩηε w #*04͕.#3͔ΒϒʔτηΫλΛϩʔυ w ϒʔτηΫλ͸#*04ίʔϧΛ༻͍ͯϒʔτϩʔμΛϩʔυˍ ࣮ߦ w ϒʔτϩʔμ͸ϖʔδςʔϒϧ΍ϨδελΛॳظԽ w

    ϒʔτϩʔμ͸ϑΝΠϧγεςϜ͔ΒΧʔωϧΛ୳ͯ͠ಡΈࠐ Έʢ*0ʹ͸#*04ίʔϧΛ࢖༻ʣ w ϒʔτϩʔμ͸$16ΛCJUϞʔυʹ੾Γସ͑ͯΧʔωϧͷ CJUΤϯτϦϙΠϯτ΁δϟϯϓ
  4. ۩ମతʹ͸Ͳ͏࣮૷͢Δͷ͔ʁ ʢ̍ʣ w ίϯιʔϧ΁ͷจࣈྻදࣔʢϒʔτϩʔμͰ͸*/5Iʣ
 printf() w σΟεΫͷಡΈࠐΈʢϒʔτϩʔμͰ͸*/5Iʣ
 fd  =  open(disk_image)


    read(fd,  buf,  len)   w ϝϞϦ΁ͷॻ͖ࠐΈ
 ctx  =  vm_open(vm_name)
 ptr  =  vm_map_gpa(ctx,  offset,  len)
 memcpy(ptr,  data,  len)
  5. ۩ମతʹ͸Ͳ͏࣮૷͢Δͷ͔ʁ ʢ̎ʣ w Ϩδελ΁ͷॻ͖ࠐΈʢηάϝϯτϨδελҎ֎ʣ
 ctx  =  vm_open(vm_name)
 vm_set_register(ctx,  cpuno,  

    VM_REG_GUEST_RFLAGS,  val)   w Ϩδελ΁ͷॻ͖ࠐΈʢηάϝϯτϨδελʣ
 ctx  =  vm_open(vm_name)
 vm_set_desc(ctx,  cpuno,  VM_REG_GUEST_CS,   base,  limit,  access)
 vm_set_register(ctx,  cpuno,   VM_REG_GUEST_CS,  selector)
  6. disk image layout • ൚༻ϒʔτϩʔμΛ࢖Θͳ͍͜ͱ ʹΑΓϒʔτ࣌ؒ୹ॖ • ΧʔωϧҾ਺ʗELFόΠφϦΛ௚઀ σΟεΫʹॻ͍͍ͯΔ •

    ϒʔτϩʔμ͸ELFόΠφϦͷΤϯ τϦϙΠϯτ΁ࣗྗͰδϟϯϓ • ΧʔωϧҾ਺ɺϝϞϦαΠζͷ৘ ใ͸ϝϞϦ্ʹஔ͍ͯmultibootͱ ޓ׵ੑͷ͋ΔܗࣜͰΧʔωϧʹ౉ ͢ MBR (boot16.S) 0 1 cmdline 64 128 blank? loader.elf 262144 bootfs (bootfs.manifest) nsectors ZFS (usr.manifest)
  7. ϒʔτίʔυΛ຋༁ʢ̍ʣ
 DNEMJOFMPBE cmdline  =  0x7e00   ! mb_info  =  0x1000

      mb_cmdline  =  (mb_info  +  16)       ! int1342_boot_struct:  #  for  command  line  ←  DAP                  .byte  0x10  ←  size  of  DAP                  .byte  0  ←  unused                  .short  0x3f      #  31.5k  ←  number  of  sectors  to  be  read                  .short  cmdline  ←  segment:offset  pointer  to  the  memory  bufferʢoffsetଆʣ                  .short  0  ←ʢsegmentଆʣ                  .quad  1  ←  absolute  number  of  the  start  of  the  sectors  to  be  read   ! init:                  xor  %ax,  %ax                  mov  %ax,  %ds  ←  DS  =  0   !                lea  int1342_boot_struct,  %si  ←  DS:SIͰDAPΛࢦఆ                  mov  $0x42,  %ah                  mov  $0x80,  %dl                  int  $0x13  ←  INT  13h  AH=42h:  Extended  Read  Sectors  From  Drive                  movl  $cmdline,  mb_cmdline  ←  mb_info-­‐>mb_cmdlineʹ0x7e00Λ୅ೖ
  8. ϒʔτίʔυΛ຋༁ʢ̍ʣ
 DNEMJOFMPBE char  *cmdline;   struct  multiboot_info_type  *mb_info;   !

    cmdline  =  vm_map_gpa(ctx,  0x7e00,  1  *   512);   pread(disk_fd,  cmdline,  0x3f  *  512,  1  *   512);   ! mb_info  =  vm_map_gpa(ctx,  0x1000,   sizeof(*mb_info));   mb_info-­‐>cmdline  =  0x7e00;  
  9. ϒʔτίʔυΛ຋༁ʢ̎ʣ
 LFSOFMMPBE tmp  =  0x80000   count32:  .short  4096  #

     in  32k  units,  4096=128MB   int1342_struct:                  .byte  0x10                  .byte  0                  .short  0x40      #  32k                  .short  0                  .short  tmp  /  16   lba:                  .quad  128   ! read_disk:                  lea  int1342_struct,  %si                  mov  $0x42,  %ah                  mov  $0x80,  %dl                  int  $0x13                  jc  done_disk                  cli                  lgdtw  gdt                  mov  $0x11,  %ax                  lmsw  %ax                  ljmp  $8,  $1f   1:                  .code32                  mov  $0x10,  %ax                  mov  %eax,  %ds                  mov  %eax,  %es                  mov  $tmp,  %esi                  mov  xfer,  %edi                  mov  $0x8000,  %ecx                  rep  movsb                  mov  %edi,  xfer                  mov  $0x20,  %al                  mov  %eax,  %ds                  mov  %eax,  %es                  ljmpw  $0x18,  $1f   1:                  .code16                  mov  $0x10,  %eax                  mov  %eax,  %cr0                  ljmpw  $0,  $1f   1:                  xor  %ax,  %ax                  mov  %ax,  %ds                  mov  %ax,  %es                  sti                  addl  $(0x8000  /  0x200),  lba                  decw  count32                  jnz  read_disk  ←  count32ճϧʔϓ   done_disk:
  10. ϒʔτίʔυΛ຋༁ʢ̎ʣ
 LFSOFMMPBE char  *target;   ! target  =  vm_map_gpa(ctx,  0x200000,

     1  *   512);   pread(disk_fd,  target,  0x40  *  4096  *   512,  128  *  512);
  11. ϒʔτίʔυΛ຋༁ʢ̏ʣ
 F mb_info  =  0x1000   mb_mmap_len  =  (mb_info  +

     44)   mb_mmap_addr  =  (mb_info  +  48)   e820data  =  0x2000   !                mov  $e820data,  %edi  ←  ES:DI   Buffer  Pointer                  mov  %edi,  mb_mmap_addr  ←  mb_info-­‐>mb_mmap_addrʹ0x2000Λ୅ೖ                  xor  %ebx,  %ebx  ←  Continuation   more_e820:                  mov  $100,  %ecx  ←  Buffer  Size                  mov  $0x534d4150,  %edx  ←  Signature  'SMAP'                    mov  $0xe820,  %ax                  add  $4,  %edi                  int  $0x15  ←  INT  15h,  AX=E820h  -­‐  Query  System  Address  Map                  jc  done_e820                  mov  %ecx,  -­‐4(%edi)                  add  %ecx,  %edi                  test  %ebx,  %ebx                  jnz  more_e820   done_e820:                  sub  $e820data,  %edi                  mov  %edi,  mb_mmap_len  ←  mb_info-­‐>mb_mmap_lenʹe820dataͷαΠζΛ୅ೖ
  12. ϒʔτίʔυΛ຋༁ʢ̏ʣ
 F struct  e820ent  *e820data;   ! e820data  =  vm_map_gpa(ctx,

     0x1100,  sizeof(struct  e820ent)  *  3);   e820data[0].ent_size  =  20;   e820data[0].addr  =  0x0;   e820data[0].size  =  654336;   e820data[0].type  =  1;   e820data[1].ent_size  =  20;   e820data[1].addr  =  0x100000;   e820data[1].size  =  mem_size  -­‐  0x100000;   e820data[1].type  =  1;   e820data[2].ent_size  =  20;   e820data[2].addr  =  0;   e820data[2].size  =  0;   e820data[2].type  =  0;   ! mb_info-­‐>mmap_addr  =  0x1100;   mb_info-­‐>mmap_length  =  sizeof(struct  e820ent)  *  3;
  13. ϒʔτίʔυΛ຋༁ʢ̐ʣ
 FOUSZUPQSPUFDUFENPEF cmdline  =  0x7e00   target  =  0x200000  

    entry  =  24+target   mb_info  =  0x1000   !                ljmp  $8,  $1f   1:                  .code32                  mov  $0x10,  %ax                  mov  %eax,  %ds                  mov  %eax,  %es                  mov  %eax,  %gs                  mov  %eax,  %fs                  mov  %eax,  %ss                  mov  $target,  %eax  ←  0x200000Λeaxʹઃఆ                  mov  $mb_info,  %ebx  ←  0x1000Λebxʹઃఆ                  jmp  *entry  ←  32bit  protected  modeͷίʔυΛಈ͔ͭ͢΋Γ͸ͳ͍ͷͰແࢹ
  14. ϒʔτίʔυΛ຋༁ʢ̑ʣ
 (%5ͷॳظԽ gdt_desc:          .short  gdt_end  -­‐

     gdt  -­‐  1          .long  gdt   ! .align  8   gdt  =  .  -­‐  8          .quad  0x00af9b000000ffff  #  64-­‐bit  code  segment          .quad  0x00cf93000000ffff  #  64-­‐bit  data  segment          .quad  0x00cf9b000000ffff  #  32-­‐bit  code  segment   gdt_end  =  .   ! lgdt  gdt_desc
  15. ϒʔτίʔυΛ຋༁ʢ̑ʣ
 (%5ͷॳظԽ /*  gdtr͸ۭ͍ͯͦ͏ͳద౰ͳྖҬʹஔ͘  */
 uint64_t  *gdtr  =  vm_map_gpa(ctx,  0x5000,

      sizeof(struct  uint64_t)  *  4);
 gdtr[0]  =  0x0;
 gdtr[1]  =  0x00af9b000000ffff;  
 gdtr[2]  =  0x00cf93000000ffff;
 gdtr[3]  =  0x00cf9b000000ffff;
 
 vm_set_desc(ctx,  0,  VM_REG_GUEST_GDTR,  gdtr,   sizeof(struct  uint64_t)  *  4  -­‐  1,  0);  
  16. ϒʔτίʔυΛ຋༁ʢ̒ʣ
 ϖʔδςʔϒϧͷॳظԽ .data   .align  4096   ident_pt_l4:    

         .quad  ident_pt_l3  +  0x67          .rept  511          .quad  0          .endr   ident_pt_l3:          .quad  ident_pt_l2  +  0x67          .rept  511          .quad  0          .endr   ident_pt_l2:          index  =  0          .rept  512          .quad  (index  <<  21)  +  0x1e7          index  =  index  +  1          .endr   ! lea  ident_pt_l4,  %eax   mov  %eax,  %cr3
  17. ϒʔτίʔυΛ຋༁ʢ̒ʣ
 ϖʔδςʔϒϧͷॳظԽ uint64_t  *PT4;
 uint64_t  *PT3;
 uint64_t  *PT2;
 
 /*

     PT4-­‐2͸ۭ͍ͯͦ͏ͳద౰ͳྖҬʹஔ͘  */
 PT4  =  vm_map_gpa(ctx,  0x4000,  sizeof(uint64_t)  *  512);
 PT3  =  vm_map_gpa(ctx,  0x3000,  sizeof(uint64_t)  *  512);
 PT2  =  vm_map_gpa(ctx,  0x2000,  sizeof(uint64_t)  *  512);
 
 for  (i  =  0;  i  <  512;  i++)  {
          PT4[i]  =  (uint64_t)  ADDR_PT3;
          PT4[i]  |=  PG_V  |  PG_RW  |  PG_U;
          PT3[i]  =  (uint64_t)  ADDR_PT2;
          PT3[i]  |=  PG_V  |  PG_RW  |  PG_U;
          PT2[i]  =  i  *  (2  *  1024  *  1024);
          PT2[i]  |=  PG_V  |  PG_RW  |  PG_PS  |  PG_U;
 }
 
 vm_set_register(ctx,  0,  VM_REG_GUEST_CR3,  0x4000);
  18. ϒʔτίʔυΛ຋༁ʢ̓ʣ
 ֤छϨδελͷઃఆ #define  BOOT_CR0  (  X86_CR0_PE  \      

                                 |  X86_CR0_WP  \                                    |  X86_CR0_PG  )   ! #define  BOOT_CR4  (  X86_CR4_DE                  \                                    |  X86_CR4_PSE                \                                    |  X86_CR4_PAE                \                                    |  X86_CR4_PGE                \                                    |  X86_CR4_PCE                \                                    |  X86_CR4_OSFXSR          \                                    |  X86_CR4_OSXMMEXCPT  )          and  $~7,  %esp          mov  $BOOT_CR4,  %eax          mov  %eax,  %cr4  ←  PAE༗ޮͳͲ          mov  $0xc0000080,  %ecx          mov  $0x00000900,  %eax          xor  %edx,  %edx          wrmsr  ←  EFERͷLMEϑϥάΛཱ͍ͯͯΔ          mov  $BOOT_CR0,  %eax          mov  %eax,  %cr0  ←  PE,PG༗ޮͳͲ
        ljmpl  $8,  $start64   .code64   .global  start64   start64:
  19. ϒʔτίʔυΛ຋༁ʢ̓ʣ
 ֤छϨδελͷઃఆ vm_set_register(ctx,  0,  VM_REG_GUEST_RSP,   ADDR_STACK);
 vm_set_register(ctx,  0,  

    VM_REG_GUEST_EFER,  0x00000d00);
 vm_set_register(ctx,  0,  VM_REG_GUEST_CR4,   0x000007b8);
 vm_set_register(ctx,  0,  VM_REG_GUEST_CR0,   0x80010001);
  20. ϒʔτίʔυΛ຋༁ʢ̔ʣ
 CJUΤϯτϦϙΠϯτ #define  BOOT_CR0  (  X86_CR0_PE  \      

                                 |  X86_CR0_WP  \                                    |  X86_CR0_PG  )   ! #define  BOOT_CR4  (  X86_CR4_DE                  \                                    |  X86_CR4_PSE                \                                    |  X86_CR4_PAE                \                                    |  X86_CR4_PGE                \                                    |  X86_CR4_PCE                \                                    |  X86_CR4_OSFXSR          \                                    |  X86_CR4_OSXMMEXCPT  )          and  $~7,  %esp          mov  $BOOT_CR4,  %eax          mov  %eax,  %cr4          mov  $0xc0000080,  %ecx          mov  $0x00000900,  %eax          xor  %edx,  %edx          wrmsr          mov  $BOOT_CR0,  %eax          mov  %eax,  %cr0
        ljmpl  $8,  $start64   .code64   .global  start64    ←  ͜͜ΛRIPʹ͍ͨ͠   start64:
  21. Αʔ͠ύύ&-'ύʔα࢖ͬͪΌ ͏ͧʔ FMG  ɺHFMG  Λ࢖ͬͯؔ਺໊ˠΞυϨεͷม׵ίʔ υΛ࣮૷ int  elfparse_open_memory(char

     *image,   size_t  size,  struct  elfparse  *ep);   int  elfparse_close(struct  elfparse  *ep);   uintmax_t  elfparse_resolve_symbol(struct   elfparse  *ep,  char  *name);
  22. ϒʔτίʔυΛ຋༁ʢ̔ʣ
 CJUΤϯτϦϙΠϯτ struct  elfparse  ep;
 uint64_t  start64;
 
 if  (elfparse_open_memory(target,

     0x40  *   4096  *  512,  &ep));
 start64  =  elfparse_resolve_symbol(&ep,   "start64");
 vm_set_register(ctx,  0,  VM_REG_GUEST_RIP,   start64);
  23. ׬੒ʂ #  /usr/local/sbin/bhyveosvload  -­‐m  1024  -­‐d  ../loader.img  osv0   sizeof

     e820data=48   cmdline=java.so  -­‐jar  /usr/mgmt/web-­‐1.0.0.jar  app  prod   start64:0x208f13   ident_pt_l4:0x8d5000   gdt_desc:0x8d8000   #  /usr/sbin/bhyve  -­‐c  1  -­‐m  1024  -­‐AI  -­‐H  -­‐P  -­‐g  0  -­‐s  0:0,hostbridge  -­‐s   1:0,virtio-­‐net,tap0  -­‐s  2:0,virtio-­‐blk,../loader.img  -­‐S  31,uart,stdio  osv0   ACPI:  RSDP  0xf0400  00024  (v02  BHYVE  )   ACPI:  XSDT  0xf0480  00034  (v01  BHYVE    BVXSDT      00000001  INTL  20130823)   ACPI:  APIC  0xf0500  0004A  (v01  BHYVE    BVMADT      00000001  INTL  20130823)   ACPI:  FACP  0xf0600  0010C  (v05  BHYVE    BVFACP      00000001  INTL  20130823)   ACPI:  DSDT  0xf0800  000F2  (v02  BHYVE    BVDSDT      00000001  INTL  20130823)   ACPI:  FACS  0xf0780  00040   Assertion  failed:  st  ==  AE_OK  (../../drivers/hpet.cc:  hpet_init:  171)   Aborted