From patchwork Tue Nov 3 14:35:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Glauber Costa X-Patchwork-Id: 57331 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nA3GZSvG028788 for ; Tue, 3 Nov 2009 16:35:28 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750879AbZKCQfT (ORCPT ); Tue, 3 Nov 2009 11:35:19 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750969AbZKCQfT (ORCPT ); Tue, 3 Nov 2009 11:35:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:10313 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750861AbZKCQfS (ORCPT ); Tue, 3 Nov 2009 11:35:18 -0500 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nA3GZI20015279; Tue, 3 Nov 2009 11:35:18 -0500 Received: from localhost.localdomain (vpn-8-137.rdu.redhat.com [10.11.8.137]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nA3GZA7J000517; Tue, 3 Nov 2009 11:35:11 -0500 From: Glauber Costa To: kvm@vger.kernel.org Cc: avi@redhat.com, qemu-devel@nongnu.org, Marcelo Tosatti , Jan Kiszka , Anthony Liguori Subject: [RFC] make cpu creation happen inside the right thread. Date: Tue, 3 Nov 2009 12:35:08 -0200 Message-Id: <1257258908-16541-1-git-send-email-glommer@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.21 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/cpu-defs.h b/cpu-defs.h index cf502e9..6d026e0 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -139,7 +139,7 @@ typedef struct CPUWatchpoint { struct qemu_work_item; struct KVMCPUState { - pthread_t thread; + pthread_t *thread; int signalled; struct qemu_work_item *queued_work_first, *queued_work_last; int regs_modified; diff --git a/hw/acpi.c b/hw/acpi.c index 7564abf..cc68188 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -781,7 +781,7 @@ void qemu_system_cpu_hot_add(int cpu, int state) CPUState *env; if (state && !qemu_get_cpu(cpu)) { - env = pc_new_cpu(model); + pc_new_cpu(model, &env); if (!env) { fprintf(stderr, "cpu %d creation failed\n", cpu); return; diff --git a/hw/pc.c b/hw/pc.c index 83012a9..53e7273 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1013,29 +1013,26 @@ int cpu_is_bsp(CPUState *env) return env->cpuid_apic_id == 0; } -CPUState *pc_new_cpu(const char *cpu_model) +void pc_new_cpu(const char *cpu_model, CPUState **env) { - CPUState *env; - - env = cpu_init(cpu_model); - if (!env) { + *env = cpu_init(cpu_model); + if (!*env) { fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } - env->kvm_cpu_state.regs_modified = 1; - if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { - env->cpuid_apic_id = env->cpu_index; + (*env)->kvm_cpu_state.regs_modified = 1; + if (((*env)->cpuid_features & CPUID_APIC) || smp_cpus > 1) { + (*env)->cpuid_apic_id = (*env)->cpu_index; /* APIC reset callback resets cpu */ - apic_init(env); + apic_init(*env); } else { - qemu_register_reset((QEMUResetHandler*)cpu_reset, env); + qemu_register_reset((QEMUResetHandler*)cpu_reset, *env); } /* kvm needs this to run after the apic is initialized. Otherwise, * it can access invalid state and crash. */ - qemu_init_vcpu(env); - return env; + qemu_init_vcpu(*env); } /* PC hardware initialisation */ @@ -1055,7 +1052,6 @@ static void pc_init1(ram_addr_t ram_size, PCIBus *pci_bus; ISADevice *isa_dev; int piix3_devfn = -1; - CPUState *env; qemu_irq *cpu_irq; qemu_irq *isa_irq; qemu_irq *i8259; @@ -1086,8 +1082,10 @@ static void pc_init1(ram_addr_t ram_size, if (kvm_enabled()) { kvm_set_boot_cpu_id(0); } + for (i = 0; i < smp_cpus; i++) { - env = pc_new_cpu(cpu_model); +// pc_new_cpu(cpu_model, &env); + kvm_init_vcpu(NULL); } vmport_init(); diff --git a/hw/pc.h b/hw/pc.h index 93eb34d..f931380 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -100,7 +100,7 @@ extern int fd_bootchk; void ioport_set_a20(int enable); int ioport_get_a20(void); -CPUState *pc_new_cpu(const char *cpu_model); +void pc_new_cpu(const char *cpu_model, CPUState **env); /* acpi.c */ extern int acpi_enabled; diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 0d263ca..4084312 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -160,6 +160,11 @@ int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes, return 0; } +void kvm_arch_create_vcpu(const char *model, CPUState **env) +{ + pc_new_cpu("qemu64", env); +} + #ifdef KVM_EXIT_TPR_ACCESS static int kvm_handle_tpr_access(CPUState *env) diff --git a/qemu-kvm.c b/qemu-kvm.c index b58a457..f83d19a 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -436,10 +436,18 @@ void kvm_disable_pit_creation(kvm_context_t kvm) kvm->no_pit_creation = 1; } -static void kvm_create_vcpu(CPUState *env, int id) + +static void kvm_create_vcpu(CPUState **_env) { long mmap_size; int r; + int id; + CPUState *env; + + kvm_arch_create_vcpu("qemu64", _env); + env = *(CPUState **)_env; + + id = env->cpu_index; r = kvm_vm_ioctl(kvm_state, KVM_CREATE_VCPU, id); if (r < 0) { @@ -1549,11 +1557,13 @@ static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo, static void on_vcpu(CPUState *env, void (*func)(void *data), void *data) { struct qemu_work_item wi; + static int remotes; if (env == current_env) { func(data); return; } + printf("remotes: %d\n", remotes++); wi.func = func; wi.data = data; @@ -1565,7 +1575,7 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data) wi.next = NULL; wi.done = false; - pthread_kill(env->kvm_cpu_state.thread, SIG_IPI); + pthread_kill(*env->kvm_cpu_state.thread, SIG_IPI); while (!wi.done) qemu_cond_wait(&qemu_work_cond); } @@ -1616,8 +1626,8 @@ void kvm_update_interrupt_request(CPUState *env) if (signal) { env->kvm_cpu_state.signalled = 1; - if (env->kvm_cpu_state.thread) - pthread_kill(env->kvm_cpu_state.thread, SIG_IPI); + if (*env->kvm_cpu_state.thread) + pthread_kill(*env->kvm_cpu_state.thread, SIG_IPI); } } } @@ -1840,7 +1850,7 @@ static void pause_all_threads(void) while (penv) { if (penv != cpu_single_env) { penv->stop = 1; - pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI); + pthread_kill(*penv->kvm_cpu_state.thread, SIG_IPI); } else { penv->stop = 0; penv->stopped = 1; @@ -1862,7 +1872,7 @@ static void resume_all_threads(void) while (penv) { penv->stop = 0; penv->stopped = 0; - pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI); + pthread_kill(*penv->kvm_cpu_state.thread, SIG_IPI); penv = (CPUState *) penv->next_cpu; } } @@ -1934,19 +1944,23 @@ static int kvm_main_loop_cpu(CPUState *env) return 0; } +extern void pc_new_cpu(const char *c, CPUState **env); + static void *ap_main_loop(void *_env) { - CPUState *env = _env; + CPUState *env; sigset_t signals; #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT struct ioperm_data *data = NULL; #endif - current_env = env; - env->thread_id = kvm_get_thread_id(); sigfillset(&signals); sigprocmask(SIG_BLOCK, &signals, NULL); - kvm_create_vcpu(env, env->cpu_index); + kvm_create_vcpu(&env); + + *(CPUState **)_env = env; + current_env = env; + env->thread_id = kvm_get_thread_id(); #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT /* do ioperm for io ports of assigned devices */ @@ -1981,12 +1995,16 @@ static void *ap_main_loop(void *_env) return NULL; } -void kvm_init_vcpu(CPUState *env) +void kvm_init_vcpu(CPUState *_env) { - pthread_create(&env->kvm_cpu_state.thread, NULL, ap_main_loop, env); + CPUState *env = NULL; + pthread_t *thread = qemu_malloc(sizeof(*thread)); + + pthread_create(thread, NULL, ap_main_loop, &env); - while (env->created == 0) + while (env == NULL) qemu_cond_wait(&qemu_vcpu_cond); + env->kvm_cpu_state.thread = thread; } int kvm_vcpu_inited(CPUState *env) diff --git a/qemu-kvm.h b/qemu-kvm.h index 525d78d..4dd50f8 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -87,6 +87,8 @@ int kvm_alloc_userspace_memory(kvm_context_t kvm, unsigned long memory, int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem); +void kvm_arch_create_vcpu(const char *model, CPUState **env); + int kvm_arch_run(CPUState *env); diff --git a/vl.c b/vl.c index 5dc7b2b..8dfae43 100644 --- a/vl.c +++ b/vl.c @@ -3570,8 +3570,6 @@ void qemu_init_vcpu(void *_env) { CPUState *env = _env; - if (kvm_enabled()) - kvm_init_vcpu(env); env->nr_cores = smp_cores; env->nr_threads = smp_threads; return;