qemu-kvmから追う仮想マシンの一生
前回はLinux KVMのソースコードを読んできましたが、
qemu-kvmは、
qemu-kvmの入手先
qemu-kvmの開発プロジェクトによる一次成果物は、
- kernel virtual machine - SourceForge.
net - URL:http://
sourceforge. net/ projects/ kvm/
本記事は、
qemu-kvmの一生 = 仮想マシンの一生
qemu-kvmは、
qemu-kvmプロセスは、
149 int kvm_init(void)
150 {
151 int fd;
152 int r, gsi_count;
153
154
155 fd = open("/dev/kvm", O_RDWR);
156 if (fd == -1) {
157 perror("open /dev/kvm");
158 return -1;
159 }
《中略》
211 return kvm_create_context();
212
213 out_close:
214 close(fd);
215 return -1;
216 }
kvm_
308 int kvm_create_vm(kvm_context_t kvm)
309 {
310 int fd;
311 #ifdef KVM_CAP_IRQ_ROUTING
312 kvm->irq_routes = qemu_mallocz(sizeof(*kvm->irq_routes));
313 kvm->nr_allocated_irq_routes = 0;
314 #endif
315
316 fd = kvm_ioctl(kvm_state, KVM_CREATE_VM, 0);
317 if (fd < 0) {
318 fprintf(stderr, "kvm_create_vm: %m\n");
319 return -1;
320 }
321 kvm_state->vmfd = fd;
322 return 0;
323 }
この後、
qemu-kvmのスレッドモデル
以下に、
qemu-kvmは、

仮想プロセッサの生成
仮想プロセッサの初期化処理は、
942 void pc_cpus_init(const char *cpu_model)
943 {
944 int i;
945
946 /* init CPUs */
947 for(i = 0; i < smp_cpus; i++) {
948 pc_new_cpu(cpu_model);
949 }
950 }
pc_
265 void qemu_init_vcpu(void *_env)
266 {
267 CPUState *env = _env;
268
269 env->nr_cores = smp_cores;
270 env->nr_threads = smp_threads;
271 if (kvm_enabled())
272 kvm_init_vcpu(env);
273 return;
274 }
kvm_
1470 int kvm_init_vcpu(CPUState *env)
1471 {
1472 pthread_create(&env->kvm_cpu_state.thread, NULL, ap_main_loop, env);
1473
1474 while (env->created == 0) {
1475 qemu_cond_wait(&qemu_vcpu_cond);
1476 }
1477
1478 return 0;
1479 }
上記の過程により、
仮想プロセッサの起動
各スレッドは、
1505 static void *ap_main_loop(void *_env)
1506 {
1507 CPUState *env = _env;
《中略》
1527 kvm_create_vcpu(env, env->cpu_index);
《中略》
1533
1534 /* and wait for machine initialization */
1535 while (!qemu_system_ready)
1536 qemu_cond_wait(&qemu_system_cond);
1537
1538 /* re-initialize cpu_single_env after re-acquiring qemu_mutex */
1539 cpu_single_env = env;
1540
1541 kvm_main_loop_cpu(env);
1542 return NULL;
1543 }
仮想プロセッサのメインループ
kvm_
1486 static int kvm_main_loop_cpu(CPUState *env)
1487 {
1488 while (1) {
1489 int run_cpu = !kvm_cpu_is_stopped(env);
1490 if (run_cpu && !kvm_irqchip_in_kernel()) {
1491 process_irqchip_events(env);
1492 run_cpu = !env->halted;
1493 }
1494 if (run_cpu) {
1495 kvm_cpu_exec(env);
1496 kvm_main_loop_wait(env, 0);
1497 } else {
1498 kvm_main_loop_wait(env, 1000);
1499 }
1500 }
1501 pthread_mutex_unlock(&qemu_mutex);
1502 return 0;
1503 }
kvm_
KVM_EXIT_*発生後のイベントディスパッチ
仮想プロセッサを実行してしばらくすると、何らかの理由により仮想プロセッサが停止し、Linux KVMからqemu-kvmに制御が戻ることになります。たとえば、仮想マシン上でデバイスI/Oが発生してLinux KVMがハードウェアエミュレーションの処理をしなければならない場合、一定時間仮想マシンの実行をしたため別の仮想マシンやプロセスへ切り替えする場合などです。
Linux KVMのカーネルモジュール内にはVMEXIT発生時のイベントハンドラが含まれていました。基本的に、
仮想マシン上でデバイスI/
kvm_
912 int kvm_cpu_exec(CPUState *env)
913 {
《中略》
941 ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
《中略》
961 switch (run->exit_reason) {
962 case KVM_EXIT_IO:
963 DPRINTF("handle_io\n");
964 ret = kvm_handle_io(run->io.port,
965 (uint8_t *)run + run->io.data_offset,
966 run->io.direction,
967 run->io.size,
968 run->io.count);
969 break;
970 case KVM_EXIT_MMIO:
971 DPRINTF("handle_mmio\n");
972 cpu_physical_memory_rw(run->mmio.phys_addr,
973 run->mmio.data,
974 run->mmio.len,
975 run->mmio.is_write);
976 ret = 1;
977 break;
978 case KVM_EXIT_IRQ_WINDOW_OPEN:
《中略》
1002 }
《中略》
1012 } while (ret > 0);
《中略》
1025 }
この先でどのような処理が行われているかは、
プロセッサ仮想化のまとめ
第4回では、
そのような状況の中で、
現在x86システムの世界で使われているx86システム仮想マシンは、
今回をもって、 これまで、次回予告