- カーネル/VM night! -
x86 CPUにejectコマンドを
組み込みたい!
@furandon_pig
自己紹介
Twitter ID: @furandon_pig
日々NetBSDを使っています。
今年は参加した勉強会で必ず一回は「NetBSD」と発する所存で
す。
(前の発表で)Go言語に関する話があったので...
今年のプリキュアはは「Go!プリンセスプリキュア」
マーケティング的(?)にGo言語の当たり年、のはず!
今日の話題
ejectコマンド。
ほぼタイトルで出オチ。
NetBSDでは以下のコマンドでCD-ROMドライブをejectできる。
$ sudo eject /dev/cd0a
これをx86に組み込むまでの(不毛な)戦い。
x86にejectコマンドを組み込む
「お前は何を言っているんだ」状態(画像略)。
CPUそのものではなく、qemuに組み込んでみる。
どの命令にejectコマンドを組み込む?
push命令が良さそう?
"eject"と命令数が同じ。
(length "eject")
5
(length "pusha")
5
libopcodesの"pusha"を"eject"に置き換えるとas,objdumpで"eject"
が指定/表示できそう。
$ hexdump -C /usr/lib/libopcodes.so.5.0 | grep pusha
00014b90 6f 76 7a 78 00 70 75 73 68 00 70 75 73 68 61 00 |ovzx.push.pusha.|
00017c10 70 75 73 68 50 00 70 6f 70 50 00 70 75 73 68 61 |pushP.popP.pusha|
が...(pushaの置き換えでは)ダメっ...!
$ objdump -d /netbsd
c010c758 <i8259_stubs>:
c010c758: 40 inc %eax
...
c010c7a8: 60 pusha
c010c7a9: 1f pop %ds
c010c7aa: 10 c0 adc %al,%al
c010c7ac: 60 pusha
上手いこと他とぶつからない命令にしないと...。
CPUID命令(eject用)(1/2)
cpuid命令にejectを組み込むのが良さそう。
diff -ur qemu-2.1.3.orig/target-i386/cpu.c qemu-2.1.3/target-i386/cpu.c
--- qemu-2.1.3.orig/target-i386/cpu.c 2015-01-23 01:19:06.000000000 +0900
+++ qemu-2.1.3/target-i386/cpu.c 2015-02-14 18:17:34.000000000 +0900
@@ -2192,7 +2192,7 @@
}
}
} else {
- if (index > env->cpuid_level)
+ if (index > env->cpuid_level && index != 0x25252)
index = env->cpuid_level;
}
@@ -2375,6 +2375,9 @@
}
break;
}
+ case 0x25252:
+ system("eject /dev/cd0a");
+ break;
case 0x80000000:
*eax = env->cpuid_xlevel;
*ebx = env->cpuid_vendor1;
CPUID命令(eject用)(2/2)
EAXレジスタのパラメータに0x25252を指定することでejectを実
行する。
# gcc -nostdlib -g -o eject_instruction eject_instruction.s
.section ".note.netbsd.ident", "a"
.int 7
.int 4
.int 0x01
.ascii "NetBSD00"
.int 0x23b419a0
.section ".text"
.balign 4
.globl _start
.type _start, @function
_start:
# execute eject command.
movl $0x25252, %eax
cpuid
# exit(EXIT_SUCCESS)
movl $0x0, (%esp)
movl $0x1, %eax
int $0x80
ret
CPUID命令でejectを実行してみる
仮想マシンを実行する(rootで実行する)
$ sudo ./i386-softmmu/qemu-system-i386 -hdd ../vnmnbsd/nbsd.vdi
ゲストOSから以下を実行する
cpuid命令を実行した時にCD-ROMがejectされる
$ gcc -nostdlib -g -o eject_instruction eject_instruction.s
$ gdb eject_instruction
...
(gdb) break _start
(gdb) run
...
Breakpoint 1, _start () at eject_instruction.s:16
16 movl $0x2525x, %eax
(gdb) stepi
17 cpuid
(gdb) stepi
まとめ
x86にejectコマンドを組み込む話。
CPUID命令にからめてejectを実行してみた。
(今年はGo言語の当たり年(のはず))

x86 CPUにejectコマンドを組み込みたい!