From patchwork Sun Apr 3 10:37:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Education Directorate X-Patchwork-Id: 8733991 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 07C599F36E for ; Sun, 3 Apr 2016 10:38:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 097512017D for ; Sun, 3 Apr 2016 10:38:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D6018200E8 for ; Sun, 3 Apr 2016 10:38:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753186AbcDCKiQ (ORCPT ); Sun, 3 Apr 2016 06:38:16 -0400 Received: from mail-pa0-f43.google.com ([209.85.220.43]:35486 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752857AbcDCKiO (ORCPT ); Sun, 3 Apr 2016 06:38:14 -0400 Received: by mail-pa0-f43.google.com with SMTP id td3so123127315pab.2 for ; Sun, 03 Apr 2016 03:38:14 -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=5STsP+heXklBtylYSj+TceUkrYxl/5Wmzi4JZzjPlVQ=; b=ha8TRcSHbd8p/XNULG27kENwZ/pKrQs/rUzBSELqix0VZbKzLFB+K6RrfHKm1josVM P3cDL7C+/4y2YqA83rrJGsMTnNJO5Gk8XteZBSbCem3rbJvb3Y8RMaGapntYrkZQH7xu UQVEHiWCNUocONXruo/SPXEKquQefzZIUwCU/rm5S+GAthFUnV73tb/BWDK09kIY1cdO nB/MA65b+cH3OhNxIaf00RimOa6TVS+EKHUN9dpHb2ApZNaiA3xdbc55t9jbiW3eT3yx gmnCPZtPgOCVm63YTX58mPtsns4Ncg63l6h4RhRkeAGTUvVBhgBhrId8a/X2EC6OnoWm mXyw== 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=5STsP+heXklBtylYSj+TceUkrYxl/5Wmzi4JZzjPlVQ=; b=HFmudp+wIsLVp3PSX2p6LzyCWcxwOhejvXTKQw1VgJwOUY7woFW16fskxJIRNNC314 eMU4bG4Iytfm8vKhK23ZTqWp3wZF6rZcidmS4YRUX/zFGW+bwHSCm1vHi0oWT1xQ5fgx GN7p6hsHjBUNsn84tBlaOksAza9gfGo6HUJX0aApb5/WSFOvHFEXxRZ0a089+XGUvCWa JjcnLnDq80KHeiPp3N/u+a2nWWxGee0fn/NqextxV3jTz9aqH9BBDTPwnECBWGLwP+Ql 4Go1Bk9hLIUnxwWp/fJ0J26bXvmq1ja9/Jz02vh0RaoZb81gXQ/E+ro7nJ7cad3XvjzZ M3Sw== X-Gm-Message-State: AD7BkJLi8NvePHUwaH0sXc6ZXqSwZPBomb7qsS1+t2o+WRD65lxukk6t+5d0C0wflbqh4A== X-Received: by 10.66.101.35 with SMTP id fd3mr44290589pab.7.1459679893591; Sun, 03 Apr 2016 03:38:13 -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 dh8sm12229830pad.46.2016.04.03.03.38.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 03 Apr 2016 03:38:12 -0700 (PDT) Received: by cotter.ozlabs.ibm.com (Postfix, from userid 1000) id DB1C1C00FF; Sun, 3 Apr 2016 20:38:03 +1000 (AEST) From: Balbir Singh To: will.deacon@arm.com, kvm@vger.kernel.org Cc: mpe@ellerman.id.au, mikey@neuling.org, aik@ozlabs.ru, Balbir Singh Subject: [KVMTOOL][PATCH 2/5] Add basic infrastructure to run tasks on vCPUs Date: Sun, 3 Apr 2016 20:37:59 +1000 Message-Id: <1459679882-30382-3-git-send-email-bsingharora@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1459679882-30382-1-git-send-email-bsingharora@gmail.com> References: <1459679882-30382-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=unavailable 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 From: Michael Ellerman 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;