Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
BHyVeでOSvを起動したい 〜BIOSがなくてもこの先生きのこるには〜
Search
Takuya ASADA
December 08, 2013
Technology
920
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
BHyVeでOSvを起動したい 〜BIOSがなくてもこの先生きのこるには〜
Takuya ASADA
December 08, 2013
More Decks by Takuya ASADA
See All by Takuya ASADA
Interrupt Affinityについて
syuu1228
0
350
僕のIntel NUCが起動しないわけがない
syuu1228
3
4.5k
Introduction to bhyve
syuu1228
1
480
OSv on bhyve
syuu1228
3
470
ruby-virtualmachine
syuu1228
0
320
10GbE時代のネットワークI/O高速化
syuu1228
14
8.9k
Play with UEFI
syuu1228
1
410
仮想化環境での利用者公平性
syuu1228
0
230
/proc/irq/<IRQ>/ smp_affinity
syuu1228
0
510
Other Decks in Technology
See All in Technology
freeeにおけるSoftware Factory
freee
PRO
0
270
CSS2026:OWS研究会・招待講演「世界観を、実装する」
atsush1_sada
2
190
From Developer Experience to Agentic Experience: The Next Evolution of APIs
benjagm
0
110
CloudWatch Logsのコスト最適化:どこまでAIに任せてどこから人間が承認すべきか
yama3133
0
160
AIネイティブ企業への変革。パーソルキャリアが挑む「データメッシュ×ガバナンス」のアーキテクチャ戦略
techtekt
PRO
0
120
DevelopersIO 2026 Tokyo 現時点の衛星通信サービスの現状を整理してみる
maroon1st
0
150
10年後、Engineering 行為を剥奪されるとして、わたしたちは、どう、何を創ればいいだろうか。 / If Engineering Is Taken Away in 10 Years, How and What Should We Create?
bitkey
PRO
1
220
企画を Software Factory-ready にする——開発が高速になったとき、PdMの仕事はどう変わったか
yachibit
1
130
生成AI時代、PMは事業責任者に進化するともっと面白い〜PMだからこそ事業構造を動かせる時代に〜
kakehashi
PRO
0
240
AI導入は済んだ。次は統制を作り替える番だ_AI×開発組織 Summit 2026
techtekt
PRO
0
500
JAWSUG TOHOKU 青森支部 「LoGoチャット」のAWS移行で 乗り越えたこと
taketakekaho
0
370
Codex を使った障害対応机上演習の実際
orgachem
PRO
0
260
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
640
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.4k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
850
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
870
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
570
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
890
Game over? The fight for quality and originality in the time of robots
wayneb77
1
310
Transcript
#)Z7FͰ04WΛىಈ͍ͨ͠ ʙ#*04͕ͳͯ͘͜ͷઌੜ ͖ͷ͜Δʹʙ !TZVV
͜Ε·Ͱͷ͓͞Β͍ w #)Z7F͍ͬͯ͡·͢ w 04W͍͡Γ͡Ί·ͨ͠ w #)Z7FͰ04WΛىಈ͍ͨ͠ w #*04͕ແ͍͔Βىಈ͠ͳ͍ʂʢ͍ͭͷྲྀΕ
OSvͱʁ • ԾԽڥ্ͰಛఆʢJavaʣΞϓϦέʔγϣϯΛޮΑ࣮͘ߦ͢ ΔࣄʹಛԽͨ͠OS • Cloudis Systems͕։ൃ KVMΛ։ൃͨ͠Qumranetͷϝϯόʔ Avi Kivity͕CTO
• KVM, XenͰಈ͘ˠAmazon EC2σϓϩΠՄೳ • BSDϥΠηϯε • http://osv.io/ • https://github.com/cloudius-systems/osv
#)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ͷ࿈ࡌΛಡΜͰԼ͍͞
04WͷϒʔτίʔυΛಡΜͰ #)Z7F༻ͷ04ϩʔμΛॻ͜͏ w 04Wͷϒʔτίʔυ͜ͷล w IUUQTHJUIVCDPNDMPVEJVTTZTUFNTPTWCMPC NBTUFSBSDIYCPPU4 w IUUQTHJUIVCDPNDMPVEJVTTZTUFNTPTWCMPC NBTUFSBSDIYCPPU4
w ॻ͍ͯΈͨ#)Z7F༻04ϩʔμͪ͜Β w IUUQTHJUIVCDPNTZVVCIZWFPTWMPBE
ήετ04ͷμΠϨΫτϒʔτ ͱ w ,7.ͰRFNVLFSOFMWNMJOV[JOJUSEJOJUSEJNH w #)Z7FͰCIZWFMPBEίϚϯυ w ϗετ04্ͰήετϚγϯʹ'SFF#4%Χʔωϧ Λϩʔυ֤͠छϨδελϖʔδςʔϒϧΛॳظ Խ͍ͯ͠Δ
w ήετϚγϯCIZWFίϚϯυ࣮ߦ࣌ʹCJUͷ ΤϯτϦϙΠϯτ͔Β࣮ߦ͞ΕΔ
#*04Λ༻͍Δैདྷͷϒʔτϓ ϩηε w #*04͕.#3͔ΒϒʔτηΫλΛϩʔυ w ϒʔτηΫλ#*04ίʔϧΛ༻͍ͯϒʔτϩʔμΛϩʔυˍ ࣮ߦ w ϒʔτϩʔμϖʔδςʔϒϧϨδελΛॳظԽ w
ϒʔτϩʔμϑΝΠϧγεςϜ͔ΒΧʔωϧΛ୳ͯ͠ಡΈࠐ Έʢ*0ʹ#*04ίʔϧΛ༻ʣ w ϒʔτϩʔμ$16ΛCJUϞʔυʹΓସ͑ͯΧʔωϧͷ CJUΤϯτϦϙΠϯτδϟϯϓ
μΠϨΫτϒʔτ࣌ͷϒʔτϓ ϩηε w Ϣʔβϗετ04্Ͱήετ04ϩʔμΛ࣮ߦ w ήετ04ϩʔμήετϚγϯͷϖʔδςʔϒϧ ήετϚγϯͷϨδελΛॳظԽ w ήετ04ϩʔμήετ04σΟεΫΠϝʔδ͔Β ΧʔωϧΛ୳ͯ͠ಡΈࠐΈ
w ήετ04ϩʔμԾ$16ΛCJUϞʔυʹΓସ ͑ͯΧʔωϧͷCJUΤϯτϦϙΠϯτδϟϯϓ
۩ମతʹͲ͏࣮͢Δͷ͔ʁ ʢ̍ʣ 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)
۩ମతʹͲ͏࣮͢Δͷ͔ʁ ʢ̎ʣ 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)
͔͜͜ΒCPPU4Λ༁։࢝ w IUUQTHJUIVCDPNDMPVEJVTTZTUFNTPTWCMPCNBTUFSBSDI YCPPU4 w .#3্ͷϒʔτηΫλʹଘࡏ w ͜͜Ͱ͍ͬͯΔ͜ͱ w σΟεΫ͔ΒΧʔωϧҾΛϩʔυ
w σΟεΫ͔ΒΧʔωϧͷ&-'όΠφϦΛϩʔυ w #*04͔ΒϝϞϦϚοϓΛऔಘ w ΧʔωϧͷCJUΤϯτϦϙΠϯτΤϯτϦ
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)
ϒʔτίʔυΛ༁ʢ̍ʣ 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Λೖ
None
ϒʔτίʔυΛ༁ʢ̍ʣ 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;
ϒʔτίʔυΛ༁ʢ̎ʣ 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:
ϒʔτίʔυΛ༁ʢ̎ʣ LFSOFMMPBE char *target; ! target = vm_map_gpa(ctx, 0x200000,
1 * 512); pread(disk_fd, target, 0x40 * 4096 * 512, 128 * 512);
ϒʔτίʔυΛ༁ʢ̏ʣ 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ͷαΠζΛೖ
ϒʔτίʔυΛ༁ʢ̏ʣ 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;
ϒʔτίʔυΛ༁ʢ̐ʣ 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ͷίʔυΛಈ͔ͭ͢Γͳ͍ͷͰແࢹ
ϒʔτίʔυΛ༁ʢ̐ʣ FOUSZUPQSPUFDUFENPEF vm_set_register(ctx, 0, VM_REG_GUEST_EAX, 0x200000); vm_set_register(ctx, 0, VM_REG_GUEST_EBX,
0x1000);
͔͜͜ΒCPPU4Λ༁։࢝ w IUUQTHJUIVCDPNDMPVEJVTTZTUFNTPTW CMPCNBTUFSBSDIYCPPU4 w ΧʔωϧͷCJUΤϯτϦϙΠϯτʹଘࡏ w ͜͜Ͱ͍ͬͯΔ͜ͱ w (%5
ϖʔδςʔϒϧͳͲΛ༻ҙͯ͠MPOH NPEFΓସ͑
ϒʔτίʔυΛ༁ʢ̑ʣ (%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
ϒʔτίʔυΛ༁ʢ̑ʣ (%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);
ϒʔτίʔυΛ༁ʢ̒ʣ ϖʔδςʔϒϧͷॳظԽ .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
ϒʔτίʔυΛ༁ʢ̒ʣ ϖʔδςʔϒϧͷॳظԽ 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);
ϒʔτίʔυΛ༁ʢ̓ʣ ֤छϨδελͷઃఆ #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:
ϒʔτίʔυΛ༁ʢ̓ʣ ֤छϨδελͷઃఆ 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);
ϒʔτίʔυΛ༁ʢ̔ʣ 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:
͋ͬʜ w ͜ͷΞυϨεɺϦϯΧͰݻఆ͞ΕͨΓͯ͠ͳ͍ ʜͲ͏͠Αʜ
Αʔ͠ύύ&-'ύʔαͬͪΌ ͏ͧʔ 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);
ϒʔτίʔυΛ༁ʢ̔ʣ 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);
ʂ # /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
σϞ
·ͱΊ w ϒʔτϩʔμΛҙਂ͘ಡΈղ͚؆ૉͳ$ίʔυͰ࣮͞Ε ͨϗετ04Ͱಈ࡞͢Δήετ04ϩʔμ༁ՄೳͰ͋Δ w #*04ͳΜͯཁΒͳ͔ͬͨ w 6&'*ͳΜͯཁΒͳ͔ͬͨ w MJCWNNBQJͷCJOEJOH͑͋͞ΕεΫϦϓτݴޠͰ࣮͠͏
Δ w ࣮൚༻04ϩʔμͱ͔։ൃ͞Εͭͭ͋Δ IUUQTHJUIVCDPNHSFIBOGSFFCTEHSVCCIZWF