From patchwork Thu Mar 31 11:28:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Education Directorate X-Patchwork-Id: 8711521 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 438729F39A for ; Thu, 31 Mar 2016 11:28:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2BFA52010C for ; Thu, 31 Mar 2016 11:28:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 01BB6200CC for ; Thu, 31 Mar 2016 11:28:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756544AbcCaL2v (ORCPT ); Thu, 31 Mar 2016 07:28:51 -0400 Received: from mail-pa0-f41.google.com ([209.85.220.41]:34531 "EHLO mail-pa0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755705AbcCaL2s (ORCPT ); Thu, 31 Mar 2016 07:28:48 -0400 Received: by mail-pa0-f41.google.com with SMTP id fe3so64657569pab.1 for ; Thu, 31 Mar 2016 04:28:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xL1JLd2KLJgcsyq16X04MntOVB/M17kbqakbtAFRza4=; b=zEa8ki9npPXLjcLVXGdfNDAva9kEh61wn1WVqxGWlINZGlwWagcHoAPXe0qax8JFhE TuUJ+p5hC3BNpDaM3zpi35zpiWSDl8gcfL6zncIkyq6IPf8z0Z72KJPrfrAs+/zlAWcc pnxdpaLmoqoiYXGeCICGu5XeDvg+GT210XRqrkJFo5B9n1sx7c4HXPeWukPAhyjNsiFp lR6bQR/XXGrl+HsYQndbb+PEBITNwIp/Seilq5J0xWAiTYeMU2Nf8CMzZnhLAKvgHM5e 4mQX2TcSHgAmYaFcFimyeQrHOV56idTeJHG5vglzgSp2eT7X6ePW1iqMWnvL42l7W5iK w9QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xL1JLd2KLJgcsyq16X04MntOVB/M17kbqakbtAFRza4=; b=EmJrZPW97osa01OOcNRpJLFNojoBPOifBOaLwI9naQB8Y1YQIWGXW8iBoM9Ck7OsmL SS2eRp4orCftxzYRoxd83IjQf8TZDGr3eyV9LK3lX/WfyZJBAWTqXnZ6z3kXS1/ipOhK S+69SMfVeipYeSXMfCmq63aMd7TX/TgAwOLtHvDAk4rP3kzOd9SFeWtTZCiOWz6V5tSv 7Ka5ogijLvQP7/JUXhxgNc9h3qurZq0L2uAvtNA5zfUGcKfMZVGZomDuDTMtZg0b4ijP hWUc73wClO3tCZF8+78kGswdrxAUkVpdNf8YeXvMOfonj2Jw7nIU+jsN3AlYK4hRVHam vXAA== X-Gm-Message-State: AD7BkJJD6cwDxyM7JOKboQgLJerpz+94D2C0+4aSGD2CNJxGwDX2CdmtG6SjGT+ay0mOyw== X-Received: by 10.66.220.101 with SMTP id pv5mr21093226pac.139.1459423723087; Thu, 31 Mar 2016 04:28:43 -0700 (PDT) Received: from cotter.ozlabs.ibm.com (14-202-194-140.static.tpgi.com.au. [14.202.194.140]) by smtp.gmail.com with ESMTPSA id l4sm12850294pfi.73.2016.03.31.04.28.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Mar 2016 04:28:42 -0700 (PDT) Received: by cotter.ozlabs.ibm.com (Postfix, from userid 1000) id 57881C007E; Thu, 31 Mar 2016 22:28:38 +1100 (AEDT) From: Balbir Singh To: will.deacon@arm.com, kvm@vger.kernel.org Cc: mpe@ellerman.id.au, mikey@neuling.org, Balbir Singh Subject: [PATCH 2/5] Add basic infrastructure to run tasks on vCPUs Date: Thu, 31 Mar 2016 22:28:24 +1100 Message-Id: <1459423707-8956-3-git-send-email-bsingharora@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1459423707-8956-1-git-send-email-bsingharora@gmail.com> References: <1459423707-8956-1-git-send-email-bsingharora@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds kvm_cpu__run_on_all_cpus() to run a task on each vCPU. This infrastructure uses signals to signal the vCPU to allow a task to be added to each vCPU's task. The vCPU executes any pending tasks in the cpu run loop Signed-off-by: Balbir Singh Signed-off-by: Michael Ellerman --- arm/include/arm-common/kvm-cpu-arch.h | 1 + include/kvm/kvm-cpu.h | 6 +++ include/kvm/kvm.h | 1 + kvm-cpu.c | 73 +++++++++++++++++++++++++++++++++++ mips/include/kvm/kvm-cpu-arch.h | 1 + powerpc/include/kvm/kvm-cpu-arch.h | 1 + x86/include/kvm/kvm-cpu-arch.h | 1 + 7 files changed, 84 insertions(+) diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h index 329979a..8a6a6e7 100644 --- a/arm/include/arm-common/kvm-cpu-arch.h +++ b/arm/include/arm-common/kvm-cpu-arch.h @@ -17,6 +17,7 @@ struct kvm_cpu { struct kvm *kvm; int vcpu_fd; struct kvm_run *kvm_run; + struct kvm_cpu_task *task; u8 is_running; u8 paused; diff --git a/include/kvm/kvm-cpu.h b/include/kvm/kvm-cpu.h index aa0cb54..4481096 100644 --- a/include/kvm/kvm-cpu.h +++ b/include/kvm/kvm-cpu.h @@ -4,6 +4,11 @@ #include "kvm/kvm-cpu-arch.h" #include +struct kvm_cpu_task { + void (*func)(struct kvm_cpu *vcpu, void *data); + void *data; +}; + int kvm_cpu__init(struct kvm *kvm); int kvm_cpu__exit(struct kvm *kvm); struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id); @@ -23,5 +28,6 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu); void kvm_cpu__show_registers(struct kvm_cpu *vcpu); void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu); void kvm_cpu__arch_nmi(struct kvm_cpu *cpu); +void kvm_cpu__run_on_all_cpus(struct kvm *kvm, struct kvm_cpu_task *task); #endif /* KVM__KVM_CPU_H */ diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h index 37155db..731abee 100644 --- a/include/kvm/kvm.h +++ b/include/kvm/kvm.h @@ -15,6 +15,7 @@ #define SIGKVMEXIT (SIGRTMIN + 0) #define SIGKVMPAUSE (SIGRTMIN + 1) +#define SIGKVMTASK (SIGRTMIN + 2) #define KVM_PID_FILE_PATH "/.lkvm/" #define HOME_DIR getenv("HOME") diff --git a/kvm-cpu.c b/kvm-cpu.c index ad4441b..4b202f8 100644 --- a/kvm-cpu.c +++ b/kvm-cpu.c @@ -4,9 +4,12 @@ #include "kvm/util.h" #include "kvm/kvm.h" #include "kvm/virtio.h" +#include "kvm/mutex.h" +#include "kvm/barrier.h" #include #include +#include #include #include #include @@ -52,6 +55,8 @@ static void kvm_cpu_signal_handler(int signum) } else if (signum == SIGKVMPAUSE) { current_kvm_cpu->paused = 1; } + + /* For SIGKVMTASK cpu->task is already set */ } static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu) @@ -83,6 +88,62 @@ void kvm_cpu__reboot(struct kvm *kvm) } } +static DEFINE_MUTEX(task_lock); +static int task_eventfd; + +static void kvm_cpu__run_task(struct kvm_cpu *cpu) +{ + u64 inc = 1; + + pr_debug("Running task %p on cpu %lu", cpu->task, cpu->cpu_id); + + /* Make sure we see the store to cpu->task */ + rmb(); + cpu->task->func(cpu, cpu->task->data); + + /* Clear task before we signal completion */ + cpu->task = NULL; + wmb(); + + if (write(task_eventfd, &inc, sizeof(inc)) < 0) + die("Failed notifying of completed task."); +} + +void kvm_cpu__run_on_all_cpus(struct kvm *kvm, struct kvm_cpu_task *task) +{ + int i, done = 0; + + pr_debug("Running task %p on all cpus", task); + + mutex_lock(&task_lock); + + for (i = 0; i < kvm->nrcpus; i++) { + if (kvm->cpus[i]->task) { + /* Should never happen */ + die("CPU %d already has a task pending!", i); + } + + kvm->cpus[i]->task = task; + wmb(); + + if (kvm->cpus[i] == current_kvm_cpu) + kvm_cpu__run_task(current_kvm_cpu); + else + pthread_kill(kvm->cpus[i]->thread, SIGKVMTASK); + } + + while (done < kvm->nrcpus) { + u64 count; + + if (read(task_eventfd, &count, sizeof(count)) < 0) + die("Failed reading task eventfd"); + + done += count; + } + + mutex_unlock(&task_lock); +} + int kvm_cpu__start(struct kvm_cpu *cpu) { sigset_t sigset; @@ -94,6 +155,7 @@ int kvm_cpu__start(struct kvm_cpu *cpu) signal(SIGKVMEXIT, kvm_cpu_signal_handler); signal(SIGKVMPAUSE, kvm_cpu_signal_handler); + signal(SIGKVMTASK, kvm_cpu_signal_handler); kvm_cpu__reset_vcpu(cpu); @@ -111,6 +173,9 @@ int kvm_cpu__start(struct kvm_cpu *cpu) cpu->needs_nmi = 0; } + if (cpu->task) + kvm_cpu__run_task(cpu); + kvm_cpu__run(cpu); switch (cpu->kvm_run->exit_reason) { @@ -217,6 +282,12 @@ int kvm_cpu__init(struct kvm *kvm) kvm->nrcpus = kvm->cfg.nrcpus; + task_eventfd = eventfd(0, 0); + if (task_eventfd < 0) { + pr_warning("Couldn't create task_eventfd"); + return task_eventfd; + } + /* Alloc one pointer too many, so array ends up 0-terminated */ kvm->cpus = calloc(kvm->nrcpus + 1, sizeof(void *)); if (!kvm->cpus) { @@ -264,6 +335,8 @@ int kvm_cpu__exit(struct kvm *kvm) kvm->nrcpus = 0; + close(task_eventfd); + return r; } core_exit(kvm_cpu__exit); diff --git a/mips/include/kvm/kvm-cpu-arch.h b/mips/include/kvm/kvm-cpu-arch.h index 3db7f2b..45e69f6 100644 --- a/mips/include/kvm/kvm-cpu-arch.h +++ b/mips/include/kvm/kvm-cpu-arch.h @@ -15,6 +15,7 @@ struct kvm_cpu { struct kvm *kvm; /* parent KVM */ int vcpu_fd; /* For VCPU ioctls() */ struct kvm_run *kvm_run; + struct kvm_cpu_task *task; struct kvm_regs regs; diff --git a/powerpc/include/kvm/kvm-cpu-arch.h b/powerpc/include/kvm/kvm-cpu-arch.h index 01eafdf..f2bfbb5 100644 --- a/powerpc/include/kvm/kvm-cpu-arch.h +++ b/powerpc/include/kvm/kvm-cpu-arch.h @@ -48,6 +48,7 @@ struct kvm_cpu { struct kvm *kvm; /* parent KVM */ int vcpu_fd; /* For VCPU ioctls() */ struct kvm_run *kvm_run; + struct kvm_cpu_task *task; struct kvm_regs regs; struct kvm_sregs sregs; diff --git a/x86/include/kvm/kvm-cpu-arch.h b/x86/include/kvm/kvm-cpu-arch.h index 89c8059..05e5bb6 100644 --- a/x86/include/kvm/kvm-cpu-arch.h +++ b/x86/include/kvm/kvm-cpu-arch.h @@ -18,6 +18,7 @@ struct kvm_cpu { struct kvm *kvm; /* parent KVM */ int vcpu_fd; /* For VCPU ioctls() */ struct kvm_run *kvm_run; + struct kvm_cpu_task *task; struct kvm_regs regs; struct kvm_sregs sregs;