qemu/accel/kvm/kvm-accel-ops.c
<<
>>
Prefs
   1/*
   2 * QEMU KVM support
   3 *
   4 * Copyright IBM, Corp. 2008
   5 *           Red Hat, Inc. 2008
   6 *
   7 * Authors:
   8 *  Anthony Liguori   <aliguori@us.ibm.com>
   9 *  Glauber Costa     <gcosta@redhat.com>
  10 *
  11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  12 * See the COPYING file in the top-level directory.
  13 *
  14 */
  15
  16#include "qemu/osdep.h"
  17#include "qemu/error-report.h"
  18#include "qemu/main-loop.h"
  19#include "sysemu/kvm_int.h"
  20#include "sysemu/runstate.h"
  21#include "sysemu/cpus.h"
  22#include "qemu/guest-random.h"
  23#include "qapi/error.h"
  24
  25#include "kvm-cpus.h"
  26
  27static void *kvm_vcpu_thread_fn(void *arg)
  28{
  29    CPUState *cpu = arg;
  30    int r;
  31
  32    rcu_register_thread();
  33
  34    qemu_mutex_lock_iothread();
  35    qemu_thread_get_self(cpu->thread);
  36    cpu->thread_id = qemu_get_thread_id();
  37    cpu->can_do_io = 1;
  38    current_cpu = cpu;
  39
  40    r = kvm_init_vcpu(cpu, &error_fatal);
  41    kvm_init_cpu_signals(cpu);
  42
  43    /* signal CPU creation */
  44    cpu_thread_signal_created(cpu);
  45    qemu_guest_random_seed_thread_part2(cpu->random_seed);
  46
  47    do {
  48        if (cpu_can_run(cpu)) {
  49            r = kvm_cpu_exec(cpu);
  50            if (r == EXCP_DEBUG) {
  51                cpu_handle_guest_debug(cpu);
  52            }
  53        }
  54        qemu_wait_io_event(cpu);
  55    } while (!cpu->unplug || cpu_can_run(cpu));
  56
  57    kvm_destroy_vcpu(cpu);
  58    cpu_thread_signal_destroyed(cpu);
  59    qemu_mutex_unlock_iothread();
  60    rcu_unregister_thread();
  61    return NULL;
  62}
  63
  64static void kvm_start_vcpu_thread(CPUState *cpu)
  65{
  66    char thread_name[VCPU_THREAD_NAME_SIZE];
  67
  68    cpu->thread = g_malloc0(sizeof(QemuThread));
  69    cpu->halt_cond = g_malloc0(sizeof(QemuCond));
  70    qemu_cond_init(cpu->halt_cond);
  71    snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
  72             cpu->cpu_index);
  73    qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
  74                       cpu, QEMU_THREAD_JOINABLE);
  75}
  76
  77static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
  78{
  79    AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
  80
  81    ops->create_vcpu_thread = kvm_start_vcpu_thread;
  82    ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
  83    ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
  84    ops->synchronize_state = kvm_cpu_synchronize_state;
  85    ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
  86}
  87
  88static const TypeInfo kvm_accel_ops_type = {
  89    .name = ACCEL_OPS_NAME("kvm"),
  90
  91    .parent = TYPE_ACCEL_OPS,
  92    .class_init = kvm_accel_ops_class_init,
  93    .abstract = true,
  94};
  95
  96static void kvm_accel_ops_register_types(void)
  97{
  98    type_register_static(&kvm_accel_ops_type);
  99}
 100type_init(kvm_accel_ops_register_types);
 101