Share
Embed
Transcript
45 slides
-
8IBUJT04W w 04WJTPQFOTPVSDF04XIJDIEFTJHOFEUPFYFDVUFB TJOHMFBQQMJDBUJPOPOUPQPGBIZQFSWJTPS w #FUUFSQFSGPSNBODF FBTZUPNBOBHF w %FWFMPQJOHCZ$MPVEJVT4ZTUFNT *TMBFMJTUBSUVQ
$PSFNFNCFSBSFDPNFGSPN2VNSBOFU $50"WJ,JWJUZ b'BUIFS`PG,7. w 0⒏DJBMTJUFIUUQPTWJP w (JUIVCIUUQHJUIVCDPNDMPVEJVTTZTUFNTPTW -
A Historical Anomaly Hardware Hypervisor Operating System JVM Application Server
Your App provides protection and abstraction provides protection and abstraction provides protection and abstraction -
Too Many Layers, Too Little Value Property/Component Hardware abstraction Isolation
Resource virtualization Backward compatibility Security Memory management I/O stack Configuration VMM OS runtime Duplication -
The new Cloud Stack - OSv Hardware Hypervisor Core JVM
Application Server Your App Single Process Kernel space only Linked to existing JVMs App sees no change -
Use cases • Rent-an-instance on a public cloud • Internal
instance on a private cloud • Pre-packaged apps ◦ MemCache, NoSQL • OEM virtual appliance -
%FTJHOPG04W w 4JOHMFQSPDFTT UISFBETVQQPSU w 4JOHMFNFNPSZTQBDF OPTXJUDIQBHFUBCMF w "QQMJDBUJPOSVOTPOLFSOFMNPEF OP
TXJUDIQSJWJMFHFNPEF w #JOBSZDPNQBUJCJMJUZXJUI-JOVYBQQ XJUITPNFMJNJUBUJPO -
04WJOUFSOBMTUSVDUVSF w 5IJO04DPSF 'SFF#4%;'4 5$1*1BOENVTM MJCD w "CMFUPMPBESVO
-JOVYCJOBSZPG 0QFO+%, OpenJDK OSv kernel FBSD code ZFS TCP/ IP COM port virtio- blk virtio- net clock ACPI sched uler ramfs VFS MM libc ELF loader syscall emu libjvm.so java.so CRuSH JRuby Sinat ra Pum a HTTP SSH 0SJHJOBMDPEFʢ$ ʣ 1PSUJOH -JOVYCJOBSZ +BWBCZUFDPEF -
$BQQPO04W w "MMBQQMJDBUJPOTIPVMECFDPNQJMFEXJUI $'-"(4 G1*$ -%'-"(4TIBSFE ˠ4IBSFEMJCSBSZ CVUXJUINBJO w
:PVDBOMPBE-JOVYTIBSFEMJCSBSZ CVUOFFEUP SFDPNQJMFFYFDVUBCMFT w -JOVYDPNQBUJCJMJUZJTJNQMFNFOUFEPOMJCDMBZFS w /PTZTDBMM -
"WBJMBCMFBQQT w 0QFO+%, w $BTTBOESB w 5PNDBU w IBQSPYZ w
NFNDBDIFE w SPHVF w NSVCZ w TRMJUF w CFODINBSLT OFUQFSG JQFSG TQFDKWN -
4VQQPSUFE)ZQFSWJTPS w -JOVY,7. w 9FO w 7JSUVBM#PY XPSLJOQSPHSFTT w
7.XBSF XPSLJOQSPHSFTT -
%FWJDFESJWFST w WJSUJPCML WJSUJPOFU w 9FO17ESJWFST w 7.XBSF17ESJWFST w 4"5"
w *%& w $0.QPSU w 7("LFZCPBSE w $MPDL )1&5 -
-FU`TTVQQPSUCIZWF w %FWJDFESJWFSTTIPVMEXPSLPOCIZWF $0.QPSU WJSUJPOFU WJSUJPCML w .BJOQSPCMFNJTCPPUMPBEFS w
CIZWFEPFTOPUIBWF#*04 OFFEUPJNQMFNFOU04-PBEFSGPS04W -
5SBEJUJPOBMCPPUQSPDFEVSF XJUI#*04 w #*04MPBETCPPUTFDUPSGSPN.#3POBEJTL w #PPUTFDUPSMPBETBOEKVNQTUPCPPUMPBEFS #*04DBMMVTFEGPS*0 w #PPUMPBEFSJOJUJBMJ[FTQBHFUBCMF
(%5BOETQFDJBMSFHJTUFST w #PPUMPBEFSMPDBUFTBOEMPBETLFSOFM #*04DBMMVTFEGPS*0 w #PPUMPBEFSTXJUDIFTUPCJUNPEF KVNQTUPLFSOFMFOUSZ QPJOU -
%JSFDUCPPU w #*04MPBETCPPUTFDUPSGSPN.#3POBEJTL w #PPUTFDUPSMPBETBOEKVNQTUPCPPUMPBEFS #*04DBMMVTFEGPS*0 w #PPUMPBEFSJOJUJBMJ[FTQBHFUBCMF (%5BOETQFDJBMSFHJTUFST
w #PPUMPBEFSMPDBUFTBOEMPBETLFSOFM #*04DBMMVTFEGPS*0 w #PPUMPBEFSTXJUDIFTUPCJUNPEF KVNQTUPLFSOFMFOUSZ QPJOU %PJUJO)PTU04 -
DPEFFYBNQMF w 1SJOUTUSJOHPODPOTPMF #*04*/5I printf() w 3FBEEJTL #*04*/5I
fd = open(disk_image) read(fd, buf, len) w NFNPSZBDDFTT ctx = vm_open(vm_name) ptr = vm_map_gpa(ctx, offset, len) memcpy(ptr, data, len) -
DPEFFYBNQMF w 3FHJTUFSXSJUF OPSNBMSFHJTUFST ctx = vm_open(vm_name) vm_set_register(ctx,
cpuno, VM_REG_GUEST_RFLAGS, val) w 3FHJTUFSXSJUF 4FHNFOUSFHJTUFST 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) -
-FU`TCFHJOUPUSBOTMBUF CPPU4 w IUUQTHJUIVCDPNDMPVEJVTTZTUFNTPTWCMPC NBTUFSBSDIYCPPU4 w *U`TPO.#3CPPUTFDUPS w -PBELFSOFMBSHVNFOUGSPNEJTL w
-PBELFSOFM&-'CJOBSZGSPNEJTL w (FUNFNPSZNBQGSPN#*04 F w &OUSZUPLFSOFMCJUQSPUFDUFENPEFDPEF -
EJTLJNBHFMBZPVUPG04W w %PFTOPUVTFTUBOEBSE CPPUMPBEFS &Y(36# UP CPPUGBTUFS w LFSOFMBSHVNFOU LFSOFM
&-'CJOBSZBSFQMBDFEPO pYFETFDUPS MBR (boot16.S) 0 1 cmdline 64 128 blank? loader.elf 262144 bootfs (bootfs.manifest) nsectors ZFS (usr.manifest) -
5SBOTMBUFCPPUDPEF 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Λೖ -
5SBOTMBUFCPPUDPEF 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; -
5SBOTMBUFCPPUDPEF 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: -
5SBOTMBUFCPPUDPEF LFSOFMMPBE char *target; ! target =
vm_map_gpa(ctx, 0x200000, 1 * 512); pread(disk_fd, target, 0x40 * 4096 * 512, 128 * 512); -
5SBOTMBUFCPPUDPEF NFNPSZNBQ 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ͷαΠζΛೖ -
5SBOTMBUFCPPUDPEF NFNPSZNBQ 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; -
5SBOTMBUFCPPUDPEF 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ͷίʔυΛಈ͔ͭ͢Γͳ͍ͷͰແࢹ -
5SBOTMBUFCPPUDPEF FOUSZUPQSPUFDUFENPEF vm_set_register(ctx, 0, VM_REG_GUEST_EAX, 0x200000); vm_set_register(ctx,
0, VM_REG_GUEST_EBX, 0x1000); -
5SBOTMBUFCPPUDPEF *OJUJBMJ[F(%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 -
5SBOTMBUFCPPUDPEF *OJUJBMJ[F(%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); -
5SBOTMBUFCPPUDPEF *OJUJBMJ[F1BHF5BCMF .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 -
5SBOTMBUFCPPUDPEF *OJUJBMJ[F1BHF5BCMF 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); -
5SBOTMBUFCPPUDPEF *OJUJBMJ[FTQFDJBMSFHJTUFSTGPSCJUNPEF #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: -
5SBOTMBUFCPPUDPEF *OJUJBMJ[FTQFDJBMSFHJTUFSTGPSCJUNPEF 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); -
5SBOTMBUFCPPUDPEF CJUFOUSZQPJOU #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 ← Want to set RIP here start64: -
-FU`TQBSTF&-'IFBEFS *NQMFNFOUTZNCPMOBNFUPBEESFTTGVODUJPO VTJOHFMG BOEHFMG JOUFMGQBSTF@PQFO@NFNPSZ DIBS JNBHF
TJ[F@U TJ[F TUSVDUFMGQBSTF FQ int elfparse_close(struct elfparse *ep); uintmax_t elfparse_resolve_symbol(struct elfparse *ep, char *name); -
5SBOTMBUFCPPUDPEF CJUFOUSZQPJOU 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); -
$PNQMFUFEJNQMFNFOUBUJPO # /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