From patchwork Tue Aug 16 07:18:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suraj Jitindar Singh X-Patchwork-Id: 9282733 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8528F60574 for ; Tue, 16 Aug 2016 07:18:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F6F228682 for ; Tue, 16 Aug 2016 07:18:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 641FF2868A; Tue, 16 Aug 2016 07:18:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C94C628682 for ; Tue, 16 Aug 2016 07:18:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751736AbcHPHSu (ORCPT ); Tue, 16 Aug 2016 03:18:50 -0400 Received: from mail-pa0-f68.google.com ([209.85.220.68]:36833 "EHLO mail-pa0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751226AbcHPHSs (ORCPT ); Tue, 16 Aug 2016 03:18:48 -0400 Received: by mail-pa0-f68.google.com with SMTP id ez1so4844231pab.3; Tue, 16 Aug 2016 00:18: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=NM0/DiYnc3fQdZ2fKtkwTcNQ6zJoNTwTOKuwIXRT/vw=; b=pqxEVKnOr0rHlBoLjNOQymHy2t8yqXPyi/SCdfYjFMmguOG6gyzyGXEiw1EHj9wQCN 4OrO+4MeFyPR7ePX/2tKPi5Wt6uhdRHPs+KNNw2+4mT/YRMMLhw780sm6O+iccNj0Bzr GxJV//DGy6eDhqCtv9tpKs6f0tt26wkk1i2eFmaTfYSjAR1cvFyDq2aC44x3HaXEeAk2 8zNTE9idsxjmcDP4S6Vx4LHK7SI6unAdS/Ug9QS43t7ubpO2HOda5b8Z6Ixh3tJYDYVf gOcKfdx3cjQA15KxR3ommrw1LCclN155Pjpw6xr2T9VjA/jMVjcGL+1QrVdL6zKyPRPV i9XA== 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=NM0/DiYnc3fQdZ2fKtkwTcNQ6zJoNTwTOKuwIXRT/vw=; b=DFcua5gjH1JvLrFIW6WKXG35MBjvYpTzlgz2YQBaO5oTrXnyY908TJNB7KUjCxVZu2 osyV0OCNg6RpsOsPds7YAIFt1ZNBSRoguBEHDsTfwM9wCs7P6tlQOAgJJcopba9hyFRB EghqKw4985bgqtuDEQHOcRfZ/ULqLiTvBpRR5OKNKd5nXHuX7iJ2L8T3+Y9x2tWSGVnS Rrimlc7PsvsNlwCJYANQQJKuOBPSSCqkABKk7H7DBHUu+NAOK1P6x9ECUVkqmR0QkpEu E/2z3OpTIkhuRKWboKJpRcXwzLdBFuE05aaY4C+fJIBSky3cu3PTYJ5cn+0p7K8Y0WUU Ej2A== X-Gm-Message-State: AEkooutmcmdUaYfHYBWkGELYFESDRRiR7QCP5XpEz5bpz2YCnUZG/2mvSoogIMeqi7cqsQ== X-Received: by 10.66.48.133 with SMTP id l5mr9128593pan.151.1471331927852; Tue, 16 Aug 2016 00:18:47 -0700 (PDT) Received: from dyn253.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id fj19sm36452252pab.37.2016.08.16.00.18.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Aug 2016 00:18:47 -0700 (PDT) From: Suraj Jitindar Singh To: kvm@vger.kernel.org Cc: sjitindarsingh@gmail.com, pbonzini@redhat.com, rkrcmar@redhat.com, kvm-ppc@vger.kernel.org, lvivier@redhat.com, thuth@redhat.com, drjones@redhat.com Subject: [kvm-unit-tests PATCH V3 3/5] lib/powerpc: Add function to start secondary threads Date: Tue, 16 Aug 2016 17:18:13 +1000 Message-Id: <1471331895-29887-3-git-send-email-sjitindarsingh@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1471331895-29887-1-git-send-email-sjitindarsingh@gmail.com> References: <1471331895-29887-1-git-send-email-sjitindarsingh@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add the lib/powerpc/smp.c file and associated header files as a place to implement generic smp functionality for inclusion in tests. Add functions start_all_cpus(), start_cpu() and start_thread() to start all stopped threads of all cpus, all stopped threads of a single cpu or a single stopped thread of a guest at a given execution location, respectively. Signed-off-by: Suraj Jitindar Singh Reviewed-by: Andrew Jones --- Change Log: V2 -> V3: - start_thread now returns int to reflect error, success or failure to start thread - start_cpu returns number of threads on cpu and number successfully started - start_all_cpus checks if number of threads started == total number of threads - 1 Signed-off-by: Suraj Jitindar Singh --- lib/powerpc/asm/smp.h | 22 ++++++++++ lib/powerpc/smp.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/ppc64/asm/smp.h | 1 + powerpc/Makefile.common | 1 + 4 files changed, 130 insertions(+) create mode 100644 lib/powerpc/asm/smp.h create mode 100644 lib/powerpc/smp.c create mode 100644 lib/ppc64/asm/smp.h diff --git a/lib/powerpc/asm/smp.h b/lib/powerpc/asm/smp.h new file mode 100644 index 0000000..21940b4 --- /dev/null +++ b/lib/powerpc/asm/smp.h @@ -0,0 +1,22 @@ +#ifndef _ASMPOWERPC_SMP_H_ +#define _ASMPOWERPC_SMP_H_ + +#include + +extern int nr_threads; + +struct start_threads { + int nr_threads; + int nr_started; +}; + +typedef void (*secondary_entry_fn)(void); + +extern void halt(void); + +extern int start_thread(int cpu_id, secondary_entry_fn entry, uint32_t r3); +extern struct start_threads start_cpu(int cpu_node, secondary_entry_fn entry, + uint32_t r3); +extern bool start_all_cpus(secondary_entry_fn entry, uint32_t r3); + +#endif /* _ASMPOWERPC_SMP_H_ */ diff --git a/lib/powerpc/smp.c b/lib/powerpc/smp.c new file mode 100644 index 0000000..48c636e --- /dev/null +++ b/lib/powerpc/smp.c @@ -0,0 +1,106 @@ +/* + * Secondary cpu support + * + * Copyright 2016 Suraj Jitindar Singh, IBM. + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ + +#include +#include +#include +#include + +int nr_threads; + +struct secondary_entry_data { + secondary_entry_fn entry; + uint64_t r3; + int nr_started; +}; + +/* + * Start stopped thread cpu_id at entry + * Returns: <0 on failure to start stopped cpu + * 0 on success + * >0 on cpu not in stopped state + */ +int start_thread(int cpu_id, secondary_entry_fn entry, uint32_t r3) +{ + int query_token, start_token, outputs[1], ret; + + query_token = rtas_token("query-cpu-stopped-state"); + start_token = rtas_token("start-cpu"); + assert(query_token != RTAS_UNKNOWN_SERVICE && + start_token != RTAS_UNKNOWN_SERVICE); + + ret = rtas_call(query_token, 1, 2, outputs, cpu_id); + if (ret) /* rtas query call failed */ + printf("query-cpu-stopped-state failed for cpu %d\n", cpu_id); + else if (!outputs[0]) { /* cpu in stopped state */ + ret = rtas_call(start_token, 3, 1, NULL, cpu_id, entry, r3); + if (ret) /* rtas start-cpu call failed */ + printf("failed to start cpu %d\n", cpu_id); + } else /* cpu not in stopped state */ + ret = outputs[0]; + + return ret; +} + +/* + * Start all stopped threads (vcpus) on cpu_node + * Returns: Number of stopped cpus which were successfully started + */ +struct start_threads start_cpu(int cpu_node, secondary_entry_fn entry, + uint32_t r3) +{ + int len, cpu, nr_threads, nr_started = 0; + const struct fdt_property *prop; + u32 *cpus; + + /* Get the id array of threads on this cpu_node */ + prop = fdt_get_property(dt_fdt(), cpu_node, + "ibm,ppc-interrupt-server#s", &len); + assert(prop); + + nr_threads = len >> 2; /* Divide by 4 since 4 bytes per cpu */ + cpus = (u32 *)prop->data; /* Array of valid cpu numbers */ + + for (cpu = 0; cpu < nr_threads; cpu++) { + if (!start_thread(fdt32_to_cpu(cpus[cpu]), entry, r3)) + nr_started++; + } + + return (struct start_threads) {nr_threads, nr_started}; +} + +static void start_each_secondary(int fdtnode, u32 regval __unused, void *info) +{ + struct secondary_entry_data *datap = info; + struct start_threads ret = start_cpu(fdtnode, datap->entry, datap->r3); + + nr_threads += ret.nr_threads; + datap->nr_started += ret.nr_started; +} + +/* + * Start all stopped cpus on the guest at entry with register 3 set to r3 + * We expect that we come in with only one thread currently started + * Returns: TRUE on success + * FALSE on failure + */ +bool start_all_cpus(secondary_entry_fn entry, uint32_t r3) +{ + struct secondary_entry_data data = { + entry, + r3, + 0 + }; + int ret; + + ret = dt_for_each_cpu_node(&start_each_secondary, &data); + assert(ret == 0); + + /* We expect that we come in with one thread already started */ + return data.nr_started == (nr_threads - 1); +} diff --git a/lib/ppc64/asm/smp.h b/lib/ppc64/asm/smp.h new file mode 100644 index 0000000..67ced75 --- /dev/null +++ b/lib/ppc64/asm/smp.h @@ -0,0 +1 @@ +#include "../../powerpc/asm/smp.h" diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common index 404194b..677030a 100644 --- a/powerpc/Makefile.common +++ b/powerpc/Makefile.common @@ -37,6 +37,7 @@ cflatobjs += lib/powerpc/setup.o cflatobjs += lib/powerpc/rtas.o cflatobjs += lib/powerpc/processor.o cflatobjs += lib/powerpc/handlers.o +cflatobjs += lib/powerpc/smp.o FLATLIBS = $(libcflat) $(LIBFDT_archive) %.elf: CFLAGS += $(arch_CFLAGS)