From patchwork Thu Oct 27 15:10:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 79738 Delivered-To: patch@linaro.org Received: by 10.80.142.83 with SMTP id 19csp720311edx; Thu, 27 Oct 2016 08:52:24 -0700 (PDT) X-Received: by 10.129.7.14 with SMTP id 14mr7399897ywh.82.1477583543971; Thu, 27 Oct 2016 08:52:23 -0700 (PDT) Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 8si2956542ywa.146.2016.10.27.08.52.23 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 27 Oct 2016 08:52:23 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42429 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzmyd-0004Qp-6x for patch@linaro.org; Thu, 27 Oct 2016 11:52:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45590) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzmTQ-0003mx-5l for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:20:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bzmTL-0004V9-MW for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:20:08 -0400 Received: from mail-wm0-x22d.google.com ([2a00:1450:400c:c09::22d]:34904) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1bzmTL-0004T2-Bw for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:20:03 -0400 Received: by mail-wm0-x22d.google.com with SMTP id e69so41517572wmg.0 for ; Thu, 27 Oct 2016 08:20:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n0ziQW3yxMnuAMxBxAJsr3u7UfjFGJJSNcsC0MuzMXI=; b=L7S8UevlDXep3fhFrEVl5/uiZprEPSpSnPf518eJxEhynobwl78sigM74bql1dAUYL YZpu4bXu4LVbzswf4Oavx5jcI5q46JAS56/tRYBZxgnpSbo9g5oJQWOurNnCYXk2iJ6W Xkkc1HgxRP0nXRC4t+79/9NJ9PkxkP3W6uLaM= 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:mime-version:content-transfer-encoding; bh=n0ziQW3yxMnuAMxBxAJsr3u7UfjFGJJSNcsC0MuzMXI=; b=hO/PXe8ajtOWquapFPIg2J/iEmd8q81hSUKVmDEBk11x6MPdir0hOZcnc+uly4lRn6 dtH0wAAssVJIctoc+yrDEggcZpglmulJJvOLpffAi/IYdfP17SQtzgtZehWvPROiIWsn hh7dT6hxVNrFHWC8kMHnq3oEjWZ9g5pKftLBlQFOWjejM7rAPyvatKGscIOflj1YnYXT y3f9w2+W80A+SIsVn/P6wgyjJfs47p89n+H8T4FuVi4t09lHyd2EMiaACaKls4cCTGA9 usqv9c8+n7pMPk3OzIPsZvT2/cdTnQWYXof7ph4CJwraqBu+u1x6jFhiMx90EI1zyPf+ ESoQ== X-Gm-Message-State: ABUngvd1NbfmsRGGROB98PktT8WMMlrdFitEUFiD9Sk6rkMp5bP7paIzKSx4d9/QuV+ZuofV X-Received: by 10.28.27.141 with SMTP id b135mr15164293wmb.78.1477581602211; Thu, 27 Oct 2016 08:20:02 -0700 (PDT) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id p4sm9044363wjo.9.2016.10.27.08.19.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 27 Oct 2016 08:19:58 -0700 (PDT) Received: from zen.linaroharston (localhost [127.0.0.1]) by zen.linaro.local (Postfix) with ESMTP id 61ABF3E04BD; Thu, 27 Oct 2016 16:11:01 +0100 (BST) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: pbonzini@redhat.com Date: Thu, 27 Oct 2016 16:10:26 +0100 Message-Id: <20161027151030.20863-30-alex.bennee@linaro.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161027151030.20863-1-alex.bennee@linaro.org> References: <20161027151030.20863-1-alex.bennee@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::22d Subject: [Qemu-devel] [PATCH v5 29/33] target-arm/powerctl: defer cpu reset work to CPU context X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mttcg@listserver.greensocs.com, peter.maydell@linaro.org, claudio.fontana@huawei.com, nikunj@linux.vnet.ibm.com, jan.kiszka@siemens.com, mark.burton@greensocs.com, a.rigo@virtualopensystems.com, qemu-devel@nongnu.org, cota@braap.org, "open list:ARM" , serge.fdrv@gmail.com, bobby.prani@gmail.com, rth@twiddle.net, =?UTF-8?q?Alex=20Benn=C3=A9e?= , fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" When switching a new vCPU on we want to complete a bunch of the setup work before we start scheduling the vCPU thread. To do this cleanly we defer vCPU setup to async work which will run the vCPUs execution context as the thread is woken up. The scheduling of the work will kick the vCPU awake. This avoids potential races in MTTCG system emulation. Signed-off-by: Alex Bennée --- target-arm/arm-powerctl.c | 144 +++++++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 58 deletions(-) -- 2.10.1 diff --git a/target-arm/arm-powerctl.c b/target-arm/arm-powerctl.c index fbb7a15..0ef4b29 100644 --- a/target-arm/arm-powerctl.c +++ b/target-arm/arm-powerctl.c @@ -48,11 +48,85 @@ CPUState *arm_get_cpu_by_id(uint64_t id) return NULL; } +struct cpu_on_info { + uint64_t entry; + uint64_t context_id; + uint32_t target_el; + bool target_aa64; +}; + + +static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, + run_on_cpu_data data) +{ + ARMCPU *target_cpu = ARM_CPU(target_cpu_state); + struct cpu_on_info *info = (struct cpu_on_info *) data.host_ptr; + + /* Initialize the cpu we are turning on */ + cpu_reset(target_cpu_state); + target_cpu->powered_off = false; + target_cpu_state->halted = 0; + + if (info->target_aa64) { + if ((info->target_el < 3) && arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) { + /* + * As target mode is AArch64, we need to set lower + * exception level (the requested level 2) to AArch64 + */ + target_cpu->env.cp15.scr_el3 |= SCR_RW; + } + + if ((info->target_el < 2) && arm_feature(&target_cpu->env, ARM_FEATURE_EL2)) { + /* + * As target mode is AArch64, we need to set lower + * exception level (the requested level 1) to AArch64 + */ + target_cpu->env.cp15.hcr_el2 |= HCR_RW; + } + + target_cpu->env.pstate = aarch64_pstate_mode(info->target_el, true); + } else { + /* We are requested to boot in AArch32 mode */ + static uint32_t mode_for_el[] = { 0, + ARM_CPU_MODE_SVC, + ARM_CPU_MODE_HYP, + ARM_CPU_MODE_SVC }; + + cpsr_write(&target_cpu->env, mode_for_el[info->target_el], CPSR_M, + CPSRWriteRaw); + } + + if (info->target_el == 3) { + /* Processor is in secure mode */ + target_cpu->env.cp15.scr_el3 &= ~SCR_NS; + } else { + /* Processor is not in secure mode */ + target_cpu->env.cp15.scr_el3 |= SCR_NS; + } + + /* We check if the started CPU is now at the correct level */ + assert(info->target_el == arm_current_el(&target_cpu->env)); + + if (info->target_aa64) { + target_cpu->env.xregs[0] = info->context_id; + target_cpu->env.thumb = false; + } else { + target_cpu->env.regs[0] = info->context_id; + target_cpu->env.thumb = info->entry & 1; + info->entry &= 0xfffffffe; + } + + /* Start the new CPU at the requested address */ + cpu_set_pc(target_cpu_state, info->entry); + g_free(info); +} + int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, uint32_t target_el, bool target_aa64) { CPUState *target_cpu_state; ARMCPU *target_cpu; + struct cpu_on_info *info; DPRINTF("cpu %" PRId64 " (EL %d, %s) @ 0x%" PRIx64 " with R0 = 0x%" PRIx64 "\n", cpuid, target_el, target_aa64 ? "aarch64" : "aarch32", entry, @@ -109,64 +183,18 @@ int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, return QEMU_ARM_POWERCTL_INVALID_PARAM; } - /* Initialize the cpu we are turning on */ - cpu_reset(target_cpu_state); - target_cpu->powered_off = false; - target_cpu_state->halted = 0; - - if (target_aa64) { - if ((target_el < 3) && arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) { - /* - * As target mode is AArch64, we need to set lower - * exception level (the requested level 2) to AArch64 - */ - target_cpu->env.cp15.scr_el3 |= SCR_RW; - } - - if ((target_el < 2) && arm_feature(&target_cpu->env, ARM_FEATURE_EL2)) { - /* - * As target mode is AArch64, we need to set lower - * exception level (the requested level 1) to AArch64 - */ - target_cpu->env.cp15.hcr_el2 |= HCR_RW; - } - - target_cpu->env.pstate = aarch64_pstate_mode(target_el, true); - } else { - /* We are requested to boot in AArch32 mode */ - static uint32_t mode_for_el[] = { 0, - ARM_CPU_MODE_SVC, - ARM_CPU_MODE_HYP, - ARM_CPU_MODE_SVC }; - - cpsr_write(&target_cpu->env, mode_for_el[target_el], CPSR_M, - CPSRWriteRaw); - } - - if (target_el == 3) { - /* Processor is in secure mode */ - target_cpu->env.cp15.scr_el3 &= ~SCR_NS; - } else { - /* Processor is not in secure mode */ - target_cpu->env.cp15.scr_el3 |= SCR_NS; - } - - /* We check if the started CPU is now at the correct level */ - assert(target_el == arm_current_el(&target_cpu->env)); - - if (target_aa64) { - target_cpu->env.xregs[0] = context_id; - target_cpu->env.thumb = false; - } else { - target_cpu->env.regs[0] = context_id; - target_cpu->env.thumb = entry & 1; - entry &= 0xfffffffe; - } - - /* Start the new CPU at the requested address */ - cpu_set_pc(target_cpu_state, entry); - - qemu_cpu_kick(target_cpu_state); + /* To avoid racing with a CPU we are just kicking off we do the + * final bit of preparation for the work in the target CPUs + * context. + */ + info = g_new(struct cpu_on_info, 1); + info->entry = entry; + info->context_id = context_id; + info->target_el = target_el; + info->target_aa64 = target_aa64; + + async_run_on_cpu(target_cpu_state, arm_set_cpu_on_async_work, + RUN_ON_CPU_HOST_PTR(info)); /* We are good to go */ return QEMU_ARM_POWERCTL_RET_SUCCESS;