arm_cpu_class_init中会调用arm_cpu_realizefn->qemu_init_vcpu
void qemu_init_vcpu(CPUState *cpu)
{
cpu->nr_cores = smp_cores;
cpu->nr_threads = smp_threads;
cpu->stopped = true;
if (!cpu->as) {
/* If the target cpu hasn't set up any address spaces itself,
* give it the default one.
*/
AddressSpace *as = address_space_init_shareable(cpu->memory,
"cpu-memory");
cpu->num_ases = 1;
cpu_address_space_init(cpu, as, 0);
}
if (kvm_enabled()) {
qemu_kvm_start_vcpu(cpu);
} else if (tcg_enabled()) {
qemu_tcg_init_vcpu(cpu);
} else {
qemu_dummy_start_vcpu(cpu);
}
}
qemu_init_vcpu 中首先给CPUState 赋值,最后如果kvm是enable的,则调用qemu_kvm_start_vcpu
static void qemu_kvm_start_vcpu(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
cpu, QEMU_THREAD_JOINABLE);
while (!cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
可见回调函数是qemu_kvm_cpu_thread_fn
static void *qemu_kvm_cpu_thread_fn(void *arg)
{
r = kvm_init_vcpu(cpu);
if (r < 0) {
fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
exit(1);
}
qemu_kvm_init_cpu_signals(cpu);
/* signal CPU creation */
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
do {
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
}
}
qemu_kvm_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu));
}
这个函数代表cpu,所以是个死循环,首先在等等待signal,如果等到signal了,就调用qemu_kvm_wait_io_event来处理
qemu_kvm_wait_io_event->qemu_kvm_eat_signals——>process_queued_cpu_work
void process_queued_cpu_work(CPUState *cpu)
{
qemu_mutex_lock(&cpu->work_mutex);
while (cpu->queued_work_first != NULL) {
wi = cpu->queued_work_first;
qemu_mutex_unlock_iothread();
start_exclusive();
wi->func(cpu, wi->data);
end_exclusive();
qemu_mutex_lock_iothread();
} else {
wi->func(cpu, wi->data);
}
qemu_mutex_lock(&cpu->work_mutex);
if (wi->free) {
g_free(wi);
} else {
atomic_mb_set(&wi->done, true);
}
}
}
这个cpu要处理的事情都在queued_work_first 这个list中,首先从这个list中拿到第一个要处理的函数
wi = cpu->queued_work_first;
然后执行这个函数的function
wi->func(cpu, wi->data);
process_queued_cpu_work 会将queued_work_first 上的事情处理完在退出.
可见在kvm中是通过一个thread来模拟cpu的运行的.
void qemu_init_vcpu(CPUState *cpu)
{
cpu->nr_cores = smp_cores;
cpu->nr_threads = smp_threads;
cpu->stopped = true;
if (!cpu->as) {
/* If the target cpu hasn't set up any address spaces itself,
* give it the default one.
*/
AddressSpace *as = address_space_init_shareable(cpu->memory,
"cpu-memory");
cpu->num_ases = 1;
cpu_address_space_init(cpu, as, 0);
}
if (kvm_enabled()) {
qemu_kvm_start_vcpu(cpu);
} else if (tcg_enabled()) {
qemu_tcg_init_vcpu(cpu);
} else {
qemu_dummy_start_vcpu(cpu);
}
}
qemu_init_vcpu 中首先给CPUState 赋值,最后如果kvm是enable的,则调用qemu_kvm_start_vcpu
static void qemu_kvm_start_vcpu(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
cpu, QEMU_THREAD_JOINABLE);
while (!cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
可见回调函数是qemu_kvm_cpu_thread_fn
static void *qemu_kvm_cpu_thread_fn(void *arg)
{
r = kvm_init_vcpu(cpu);
if (r < 0) {
fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
exit(1);
}
qemu_kvm_init_cpu_signals(cpu);
/* signal CPU creation */
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
do {
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
}
}
qemu_kvm_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu));
}
这个函数代表cpu,所以是个死循环,首先在等等待signal,如果等到signal了,就调用qemu_kvm_wait_io_event来处理
qemu_kvm_wait_io_event->qemu_kvm_eat_signals——>process_queued_cpu_work
void process_queued_cpu_work(CPUState *cpu)
{
qemu_mutex_lock(&cpu->work_mutex);
while (cpu->queued_work_first != NULL) {
wi = cpu->queued_work_first;
qemu_mutex_unlock_iothread();
start_exclusive();
wi->func(cpu, wi->data);
end_exclusive();
qemu_mutex_lock_iothread();
} else {
wi->func(cpu, wi->data);
}
qemu_mutex_lock(&cpu->work_mutex);
if (wi->free) {
g_free(wi);
} else {
atomic_mb_set(&wi->done, true);
}
}
}
这个cpu要处理的事情都在queued_work_first 这个list中,首先从这个list中拿到第一个要处理的函数
wi = cpu->queued_work_first;
然后执行这个函数的function
wi->func(cpu, wi->data);
process_queued_cpu_work 会将queued_work_first 上的事情处理完在退出.
可见在kvm中是通过一个thread来模拟cpu的运行的.