From patchwork Tue Apr 30 14:00:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 793321 Delivered-To: patch@linaro.org Received: by 2002:a05:6000:54f:b0:34d:5089:5a9e with SMTP id b15csp275962wrf; Tue, 30 Apr 2024 07:02:11 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCX/8nBidEcR1PdWPXy3qKH2jq0WF21/Ac3hzjQMdPC/wYF5q5GWozdVKfb64DH6fkJwrMFumwxMCK3oFueSuAFW X-Google-Smtp-Source: AGHT+IGUIPkXRjxuV+QLG4tXssKW8Jm2voqn8XC4yALfdu3uEP3I0PmNmEjMh0i4Z+ES5EbudhX7 X-Received: by 2002:a67:efc4:0:b0:47b:b817:f31f with SMTP id s4-20020a67efc4000000b0047bb817f31fmr12516600vsp.9.1714485728274; Tue, 30 Apr 2024 07:02:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1714485728; cv=none; d=google.com; s=arc-20160816; b=KB1EA9eEY7Zpy7HOLtOYjcOP+JE5MD9QuDwnzgtdJoNTm1fQHNKcZYakFqiSp3ncKv vaa+1kr9/0IsylvmfkKi84FtjHkKWPoaxiJwOSiF+XP+22K0K1jcaNXe60h7wQura3Mc V8qaeH1CRr4ynzjr2/ol3E3yD1NS3to4UF2CsJ8C1rzc6cdaTH8LSDHqXypz7F35CJBt eFGZAxx3f3ebRbpmmnD/q9jqgRjiG9aOM10awz0EkbijTJtpvmxRxtfnG6zRp+WboMtT Wu/LeybMT5rA88PaWb2Ux6UpVg0pK+ZDAmG/COmnKgubQ92Q8etoEJrCDgasqFZP7Zqa m9QQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=pdw4e1T+XOnjRYbe6abw8/6ufHXzK4jmHY6mtjifRb8=; fh=68wiIGPkWm/0azCHzpRXqXi5Lsy/uB/434VAMxZd7RM=; b=UeX2+G9ds4XEEBl9m2uKa+hJjdHef4AOD/JFZEgMWZ+tt3efCiVPhdmmEQPsfOJnpA uTHNP/QCufMg22xsx4WYgyU3ZeGsqkQSOcdZZCE5zDt1AnObjAUVcQzWuBGLKxfzsrsE vsj1G2sNZMCKVocR2A5+WQg5x9YAAB59lgTY6Q9yYfV3LlqakMSPxKmidf2LqlfX4WCr wtgcKvxG+4Qr+5UyS9k6sRUWd4klOREIB8uHCWg0oj52bdc5iq6/CfSY5SR18PBy8E3N xvXU2tvY44cO18fOQujdaVJ/geWq4EWSPa62EvhKiXtUQLQ46lP2/R0YiWyrDlK3jGnF WuOw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=COx0NkUK; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id j6-20020a67ef06000000b0047270645a06si4526965vsr.511.2024.04.30.07.02.08 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 30 Apr 2024 07:02:08 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=COx0NkUK; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1s1o2g-0002eW-W1; Tue, 30 Apr 2024 10:01:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1s1o2U-0002Yv-7u for qemu-devel@nongnu.org; Tue, 30 Apr 2024 10:01:05 -0400 Received: from mail-lj1-x22c.google.com ([2a00:1450:4864:20::22c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1s1o2O-0002uI-MS for qemu-devel@nongnu.org; Tue, 30 Apr 2024 10:00:54 -0400 Received: by mail-lj1-x22c.google.com with SMTP id 38308e7fff4ca-2d858501412so73687181fa.0 for ; Tue, 30 Apr 2024 07:00:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1714485649; x=1715090449; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=pdw4e1T+XOnjRYbe6abw8/6ufHXzK4jmHY6mtjifRb8=; b=COx0NkUKj6lNJihspMIjN8j+xzj7zsugmcVCAO++jt7IcUNHfCUBJDIkQHBJ512o/B oIZRL33quWqdEwO6FQf+gp6yV9am0IwyucIedOefLzxzTZGKcc5iXQMDwGQoULYfN6OX OTWkvuBBQBzUYs/7w/ye/ytXk2fl2vN9hq5ts10qRcqUPqmHIVKSsH61vxNxWb3PM9hx cSS83+/t/H6RfheAaoHw+dfYinfJlxJtfAjnNI6AMVhyxm2NDErdYkYuILCfzOhuR5gq HREh2J8+BlOLTM48TS6r8m3BVXVJ/0VGgn2VwgzJnmjKMuRSzuzO+8Qeo/EwdicxGxdS YCkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714485649; x=1715090449; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pdw4e1T+XOnjRYbe6abw8/6ufHXzK4jmHY6mtjifRb8=; b=cRTfF2pJWg+Qsm2DHA1LRfy7pBvBDr9ZnRIMeVNpsELkL32IFS1Q9zzZoDM7yz4d8J N3YjIUDP5wtJ7qn3tNCMwTvrEHIC1q/vCaTPEWSvB9JMXK1OBlurJb1Z3AML9xoiYrJN gvbmteO+1mo8T+ORCnrCrpvGdms3tNEZ7uHtJvRLxRXTZrpXSVHpmrFOyl5Jlbtfk7/R l9UxL97SOqsKfiSUi8sCQV5R71F2Ka7aX7SM9cSwKyLVNWMcVivadqfHDpkjxlRzGPtS hsZ+UATafShlGIhLtloqXdMVPlpKr2Vr1+ttVVwnmsqdgIvBa/07lbuOhn/qaM2ktChh h+Mg== X-Forwarded-Encrypted: i=1; AJvYcCXAZpl/uI26GybRENxmE/C1cw6Do2lpc+xcAc0W4BQO/n5nbI4LOocVnrdAf5jS6/CzsCQRRv8RG0Alc/s6etjrNIzdlsw= X-Gm-Message-State: AOJu0YwvCA2fxVARhSr+QN4DJpCW8x1IRhT/x8EGYg00HnRp0bH2CR5Y T5vUt/NXxaRO2Xjfr6ju/E0Jj06dQe+7isDkuz4fW/A7UdYnboiE9qNsRKWln2s= X-Received: by 2002:a2e:8750:0:b0:2de:25e2:6187 with SMTP id q16-20020a2e8750000000b002de25e26187mr1967189ljj.23.1714485639231; Tue, 30 Apr 2024 07:00:39 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id v10-20020a05600c470a00b0041bfa349cadsm11062705wmo.16.2024.04.30.07.00.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Apr 2024 07:00:37 -0700 (PDT) From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH 1/2] accel/tcg: Make TCGCPUOps::cpu_exec_halt return bool for whether to halt Date: Tue, 30 Apr 2024 15:00:34 +0100 Message-Id: <20240430140035.3889879-2-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240430140035.3889879-1-peter.maydell@linaro.org> References: <20240430140035.3889879-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::22c; envelope-from=peter.maydell@linaro.org; helo=mail-lj1-x22c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org The TCGCPUOps::cpu_exec_halt method is called from cpu_handle_halt() when the CPU is halted, so that a target CPU emulation can do anything target-specific it needs to do. (At the moment we only use this on i386.) The current specification of the method doesn't allow the target specific code to do something different if the CPU is about to come out of the halt state, because cpu_handle_halt() only determines this after the method has returned. (If the method called cpu_has_work() itself this would introduce a potential race if an interrupt arrived between the target's method implementation checking and cpu_handle_halt() repeating the check.) Change the definition of the method so that it returns a bool to tell cpu_handle_halt() whether to stay in halt or not. We will want this for the Arm target, where FEAT_WFxT wants to do some work only for the case where the CPU is in halt but about to leave it. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- include/hw/core/tcg-cpu-ops.h | 11 +++++++++-- target/i386/tcg/helper-tcg.h | 2 +- accel/tcg/cpu-exec.c | 7 +++++-- target/i386/tcg/sysemu/seg_helper.c | 3 ++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h index dc1f16a9777..f3ac76e6f6d 100644 --- a/include/hw/core/tcg-cpu-ops.h +++ b/include/hw/core/tcg-cpu-ops.h @@ -111,8 +111,15 @@ struct TCGCPUOps { void (*do_interrupt)(CPUState *cpu); /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */ bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request); - /** @cpu_exec_halt: Callback for handling halt in cpu_exec */ - void (*cpu_exec_halt)(CPUState *cpu); + /** + * @cpu_exec_halt: Callback for handling halt in cpu_exec. + * + * Return true to indicate that the CPU should now leave halt, false + * if it should remain in the halted state. + * If this method is not provided, the default is to leave halt + * if cpu_has_work() returns true. + */ + bool (*cpu_exec_halt)(CPUState *cpu); /** * @tlb_fill: Handle a softmmu tlb miss * diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index effc2c1c984..85957943bf3 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -39,7 +39,7 @@ QEMU_BUILD_BUG_ON(TCG_PHYS_ADDR_BITS > TARGET_PHYS_ADDR_SPACE_BITS); */ void x86_cpu_do_interrupt(CPUState *cpu); #ifndef CONFIG_USER_ONLY -void x86_cpu_exec_halt(CPUState *cpu); +bool x86_cpu_exec_halt(CPUState *cpu); bool x86_need_replay_interrupt(int interrupt_request); bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req); #endif diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 5c70748060a..550f93b19ce 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -669,11 +669,14 @@ static inline bool cpu_handle_halt(CPUState *cpu) #ifndef CONFIG_USER_ONLY if (cpu->halted) { const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; + bool leave_halt; if (tcg_ops->cpu_exec_halt) { - tcg_ops->cpu_exec_halt(cpu); + leave_halt = tcg_ops->cpu_exec_halt(cpu); + } else { + leave_halt = cpu_has_work(cpu); } - if (!cpu_has_work(cpu)) { + if (!leave_halt) { return true; } diff --git a/target/i386/tcg/sysemu/seg_helper.c b/target/i386/tcg/sysemu/seg_helper.c index 2db8083748e..9ba94deb3aa 100644 --- a/target/i386/tcg/sysemu/seg_helper.c +++ b/target/i386/tcg/sysemu/seg_helper.c @@ -128,7 +128,7 @@ void x86_cpu_do_interrupt(CPUState *cs) } } -void x86_cpu_exec_halt(CPUState *cpu) +bool x86_cpu_exec_halt(CPUState *cpu) { if (cpu->interrupt_request & CPU_INTERRUPT_POLL) { X86CPU *x86_cpu = X86_CPU(cpu); @@ -138,6 +138,7 @@ void x86_cpu_exec_halt(CPUState *cpu) cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL); bql_unlock(); } + return cpu_has_work(cpu); } bool x86_need_replay_interrupt(int interrupt_request) From patchwork Tue Apr 30 14:00:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 793322 Delivered-To: patch@linaro.org Received: by 2002:a05:6000:54f:b0:34d:5089:5a9e with SMTP id b15csp276158wrf; Tue, 30 Apr 2024 07:02:24 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVSNQfxfTaxQM5z5Wlynxjfawp7rH4pnKHHAGIqtBgHCEKpQtsHKJGZigc0Is3b+PI3M71pw9hwyJEABWhnDacc X-Google-Smtp-Source: AGHT+IGN1YPx39A4/uDuoe8THuXyu+CMnG63/QcGodqGui6MVmOCVclIBPXemas0ynOhFYj5OfJX X-Received: by 2002:a05:690c:6805:b0:61b:342e:b0cd with SMTP id id5-20020a05690c680500b0061b342eb0cdmr13149505ywb.24.1714485744637; Tue, 30 Apr 2024 07:02:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1714485744; cv=none; d=google.com; s=arc-20160816; b=aKfbeOq3A5rAY5L/Ax9YecuyjiRkWigSmbvxqtdq6fIq2ZokpK2GQaQqfO68GYDZCK /AqXjoKShCTTzcjlAhju8GotN19TsDGR6+7LOYn2VOT55jzKjsu8Oqv3ARq9mWhXY7N0 rhg3YY0QPLJ/vI2SPfbdQKTnZtxDZ0LxPpUGVRE6sHvmkp+RSVCRBDlkgb0ai2yJT6td e2lOYZQKU3hZMLj3BRhyzG99t6O7+DzFDV99Du429AVy4yao3LUqUfcUZ7e4e0Fc68zg +XUTyVgyPlrw+hDXmdSDmsOAYHHoLujGUrUG5jPXLdIY402UxQ0FiFn7RkEm9Cc3fwVU oxnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature; bh=xJf8wNVMGR0MP4vhP++ZGvQJmrzt6ceEedWUAcLKAGY=; fh=ZNl6rFkap8b3hUfjKTBVNuBsHn4E9EAQycd1hb0MU8Q=; b=qBL4gtVVeFXUzn0UCaLAU8wfX/6dGdTxbT8OpUfiedU65Un+IqoiEbcswIT3W98/V6 Yzb1di0BUrXNeIqledhnf/4lKocRW3hCOQGzUWXfyvANqUFV30Ky/q9mZx2MKpzN0bUI 9JHyRSPBYhjNIhH2i4aXQETIAtA8bPrPECgbNAt9tdNmqTJxJUbd96AKdgVNjcGUo7yA bzzKYYKbYofJRLa0xVpW9YibG7cmRii3hEagj69dEe7/YoJMEKfZ+xi/ZfdUcS983Hf6 MGi+fRmhA0uYq68K6sGlqU+nlrwgbqbsA/b0pN69ccoJqxGtuOYWdGHdgHaataN1qz2u 2JzQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xnASAZ1P; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id p127-20020a81b185000000b00618127a541dsi13416173ywh.414.2024.04.30.07.02.24 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 30 Apr 2024 07:02:24 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xnASAZ1P; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1s1o2e-0002cY-38; Tue, 30 Apr 2024 10:01:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1s1o2L-0002X9-AA for qemu-devel@nongnu.org; Tue, 30 Apr 2024 10:00:50 -0400 Received: from mail-lj1-x232.google.com ([2a00:1450:4864:20::232]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1s1o2H-0002tS-KN for qemu-devel@nongnu.org; Tue, 30 Apr 2024 10:00:49 -0400 Received: by mail-lj1-x232.google.com with SMTP id 38308e7fff4ca-2dd6a7ae2dcso91530231fa.1 for ; Tue, 30 Apr 2024 07:00:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1714485643; x=1715090443; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=xJf8wNVMGR0MP4vhP++ZGvQJmrzt6ceEedWUAcLKAGY=; b=xnASAZ1PA05FAMPPNF3y9NJgjOmeJBz2pwPFWI39n2Ock9mVKCaDdXBXhLKEuoVLX1 fvRDJBYS8+ad1FZGQ2DM3rpdmWLgliBYaIz4OAwkDZPxGknBbM/K6yrsTJbvJoWNelzr vmfC3+YEEAr7U2kj6PocgKoWouYBc1+xsr37Wj+Sk2tirpMOk6u0nh4Ib7V6ynulW/Y3 +h6ysRL4Wg2k7mPo2u2DCj1optrQt9qRvYpSnLAgfI0VPbdyX/6/8q4IiC4U6EHcov1g K45WZWILQ+1SmyRxCSi5a8fF3F2rJHH4262LmbRCVrghUMyJ67Eqe+YQPRO6hcvV04RA Pflg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714485643; x=1715090443; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xJf8wNVMGR0MP4vhP++ZGvQJmrzt6ceEedWUAcLKAGY=; b=v+WX7l0rUR/+aUfmcflrOQer9WYufn85y5aRdfjXAEUIFqpoYxiyhkT1QdF7WXoxc4 D9ZlEN0Y4X4Xky12Md+EoN2NW2UiKo5x0QaDSkARCIVvVrnkOGLPUAesYhQ5JaaAmpW3 oTgtkQPSAf6IuipJDPq132RxRezbFkNKJzupV42UJv35BUy8SHvZxVpNLwMoRqL+PqCa AGMwRcxehAe0xdAymsQH0esIm0pYsGJMdM7jUUDC+QGVAdSQJuGBLl6ZPBJM7YAP4N91 4HRo043K7nACEHpUEDzWciZz9GLG7/U/4YcjKQ8Sq32uqfgS6DkzpLUoUdPDO4ZANFsb jOmQ== X-Forwarded-Encrypted: i=1; AJvYcCU4x5nnw7xgcm4tOKjho7e7FMTNc0y9J0kzj7NP/2HeO1cEglJGz3JaZNdxPtY1/yCcCLEdHE/K5Ck39V5j81G6fnR/bqc= X-Gm-Message-State: AOJu0YxbXm+cLIlQD/B7qNEQ/IOtShQow0oP7VA5IwNVY0rOFSH4BdjH ihMCkWXbbh4vWfzJ6rI9iuxB8bj3QDBLAPovJcNlyFeYpO0GfFX+m8CVnUW2Qdw= X-Received: by 2002:a2e:2a06:0:b0:2e0:c363:f9dc with SMTP id q6-20020a2e2a06000000b002e0c363f9dcmr3196323ljq.40.1714485642898; Tue, 30 Apr 2024 07:00:42 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id v10-20020a05600c470a00b0041bfa349cadsm11062705wmo.16.2024.04.30.07.00.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Apr 2024 07:00:42 -0700 (PDT) From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH 2/2] target/arm: Implement FEAT WFxT and enable for '-cpu max' Date: Tue, 30 Apr 2024 15:00:35 +0100 Message-Id: <20240430140035.3889879-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240430140035.3889879-1-peter.maydell@linaro.org> References: <20240430140035.3889879-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::232; envelope-from=peter.maydell@linaro.org; helo=mail-lj1-x232.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org FEAT_WFxT introduces new instructions WFIT and WFET, which are like the existing WFI and WFE but allow the guest to pass a timeout value in a register. The instructions will wait for an interrupt/event as usual, but will also stop waiting when the value of CNTVCT_EL0 is greater than or equal to the specified timeout value. We implement WFIT by setting up a timer to expire at the right point; when the timer expires it sets the EXITTB interrupt, which will cause the CPU to leave the halted state. If we come out of halt for some other reason, we unset the pending timer. We implement WFET as a nop, which is architecturally permitted and matches the way we currently make WFE a nop. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- docs/system/arm/emulation.rst | 1 + target/arm/cpu-features.h | 5 ++++ target/arm/cpu.h | 3 ++ target/arm/helper.h | 1 + target/arm/internals.h | 8 +++++ target/arm/tcg/a64.decode | 4 +++ target/arm/cpu.c | 38 ++++++++++++++++++++++++ target/arm/helper.c | 4 +-- target/arm/machine.c | 20 +++++++++++++ target/arm/tcg/cpu64.c | 1 + target/arm/tcg/op_helper.c | 54 ++++++++++++++++++++++++++++++++++ target/arm/tcg/translate-a64.c | 41 ++++++++++++++++++++++++++ 12 files changed, 178 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index a9ae7ede9fc..d283c985d14 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -108,6 +108,7 @@ the following architecture extensions: - FEAT_UAO (Unprivileged Access Override control) - FEAT_VHE (Virtualization Host Extensions) - FEAT_VMID16 (16-bit VMID) +- FEAT_WFxT (WFE and WFI instructions with timeout) - FEAT_XNX (Translation table stage 2 Unprivileged Execute-never) - SVE (The Scalable Vector Extension) - SVE2 (The Scalable Vector Extension v2) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index b300d0446d8..c59ca104fe1 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -571,6 +571,11 @@ static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; } +static inline bool isar_feature_aa64_wfxt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, WFXT) >= 2; +} + static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 97997dbd087..e8e6024fe30 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -868,6 +868,9 @@ struct ArchCPU { * pmu_op_finish() - it does not need other handling during migration */ QEMUTimer *pmu_timer; + /* Timer used for WFxT timeouts */ + QEMUTimer *wfxt_timer; + /* GPIO outputs for generic timer */ qemu_irq gt_timer_outputs[NUM_GTIMERS]; /* GPIO output for GICv3 maintenance interrupt signal */ diff --git a/target/arm/helper.h b/target/arm/helper.h index 2b027333053..a85de78c8fc 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -53,6 +53,7 @@ DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) DEF_HELPER_1(wfe, void, env) +DEF_HELPER_2(wfit, void, env, i64) DEF_HELPER_1(yield, void, env) DEF_HELPER_1(pre_hvc, void, env) DEF_HELPER_2(pre_smc, void, env, i32) diff --git a/target/arm/internals.h b/target/arm/internals.h index b53f5e8ff2a..bd32883890d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1760,4 +1760,12 @@ bool check_watchpoint_in_range(int i, target_ulong addr); CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr); int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type); int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type); + +/* Return the current value of the system counter in ticks */ +uint64_t gt_get_countervalue(CPUARMState *env); +/* + * Return the currently applicable offset between the system counter + * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2). + */ +uint64_t gt_virt_cnt_offset(CPUARMState *env); #endif diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode index 0e7656fd158..7aea5cba5ea 100644 --- a/target/arm/tcg/a64.decode +++ b/target/arm/tcg/a64.decode @@ -183,6 +183,10 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB NOP 1101 0101 0000 0011 0010 ---- --- 11111 } +# System instructions with register argument +WFET 1101 0101 0000 0011 0001 0000 000 rd:5 +WFIT 1101 0101 0000 0011 0001 0000 001 rd:5 + # Barriers CLREX 1101 0101 0000 0011 0011 ---- 010 11111 diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a152def2413..006092a6b12 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1132,6 +1132,33 @@ static bool arm_cpu_virtio_is_big_endian(CPUState *cs) return arm_cpu_data_is_big_endian(env); } +static bool arm_cpu_exec_halt(CPUState *cs) +{ + bool leave_halt = cpu_has_work(cs); + + if (leave_halt) { + /* We're about to come out of WFI/WFE: disable the WFxT timer */ + ARMCPU *cpu = ARM_CPU(cs); + if (cpu->wfxt_timer) { + timer_del(cpu->wfxt_timer); + } + } + return leave_halt; +} + +static void arm_wfxt_timer_cb(void *opaque) +{ + ARMCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + + /* + * We expect the CPU to be halted; this will cause arm_cpu_is_work() + * to return true (so we will come out of halt even with no other + * pending interrupt), and the TCG accelerator's cpu_exec_interrupt() + * function auto-clears the CPU_INTERRUPT_EXITTB flag for us. + */ + cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); +} #endif static void arm_disas_set_info(CPUState *cpu, disassemble_info *info) @@ -1874,6 +1901,9 @@ static void arm_cpu_finalizefn(Object *obj) if (cpu->pmu_timer) { timer_free(cpu->pmu_timer); } + if (cpu->wfxt_timer) { + timer_free(cpu->wfxt_timer); + } #endif } @@ -2357,6 +2387,13 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) #endif } +#ifndef CONFIG_USER_ONLY + if (tcg_enabled() && cpu_isar_feature(aa64_wfxt, cpu)) { + cpu->wfxt_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + arm_wfxt_timer_cb, cpu); + } +#endif + if (tcg_enabled()) { /* * Don't report some architectural features in the ID registers @@ -2611,6 +2648,7 @@ static const TCGCPUOps arm_tcg_ops = { #else .tlb_fill = arm_cpu_tlb_fill, .cpu_exec_interrupt = arm_cpu_exec_interrupt, + .cpu_exec_halt = arm_cpu_exec_halt, .do_interrupt = arm_cpu_do_interrupt, .do_transaction_failed = arm_cpu_do_transaction_failed, .do_unaligned_access = arm_cpu_do_unaligned_access, diff --git a/target/arm/helper.c b/target/arm/helper.c index 6b224826fbb..f7bb2d6ba8a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -2658,7 +2658,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env, } } -static uint64_t gt_get_countervalue(CPUARMState *env) +uint64_t gt_get_countervalue(CPUARMState *env) { ARMCPU *cpu = env_archcpu(env); @@ -2793,7 +2793,7 @@ static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) return gt_get_countervalue(env) - gt_phys_cnt_offset(env); } -static uint64_t gt_virt_cnt_offset(CPUARMState *env) +uint64_t gt_virt_cnt_offset(CPUARMState *env) { uint64_t hcr; diff --git a/target/arm/machine.c b/target/arm/machine.c index b2b39b24755..0a722ca7e75 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -242,6 +242,25 @@ static const VMStateDescription vmstate_irq_line_state = { } }; +static bool wfxt_timer_needed(void *opaque) +{ + ARMCPU *cpu = opaque; + + /* We'll only have the timer object if FEAT_WFxT is implemented */ + return cpu->wfxt_timer; +} + +static const VMStateDescription vmstate_wfxt_timer = { + .name = "cpu/wfxt-timer", + .version_id = 1, + .minimum_version_id = 1, + .needed = wfxt_timer_needed, + .fields = (const VMStateField[]) { + VMSTATE_TIMER_PTR(wfxt_timer, ARMCPU), + VMSTATE_END_OF_LIST() + } +}; + static bool m_needed(void *opaque) { ARMCPU *cpu = opaque; @@ -957,6 +976,7 @@ const VMStateDescription vmstate_arm_cpu = { #endif &vmstate_serror, &vmstate_irq_line_state, + &vmstate_wfxt_timer, NULL } }; diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index 62c4663512b..47ea51d3aa5 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -1150,6 +1150,7 @@ void aarch64_max_tcg_initfn(Object *obj) t = cpu->isar.id_aa64isar2; t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */ t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */ + t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2); /* FEAT_WFxT */ cpu->isar.id_aa64isar2 = t; t = cpu->isar.id_aa64pfr0; diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index c199b69fbff..c083e5cfb87 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -409,6 +409,60 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) #endif } +void HELPER(wfit)(CPUARMState *env, uint64_t timeout) +{ +#ifdef CONFIG_USER_ONLY + /* + * WFI in the user-mode emulator is technically permitted but not + * something any real-world code would do. AArch64 Linux kernels + * trap it via SCTRL_EL1.nTWI and make it an (expensive) NOP; + * AArch32 kernels don't trap it so it will delay a bit. + * For QEMU, make it NOP here, because trying to raise EXCP_HLT + * would trigger an abort. + */ + return; +#else + ARMCPU *cpu = env_archcpu(env); + CPUState *cs = env_cpu(env); + int target_el = check_wfx_trap(env, false); + /* The WFIT should time out when CNTVCT_EL0 >= the specified value. */ + uint64_t cntval = gt_get_countervalue(env); + uint64_t offset = gt_virt_cnt_offset(env); + uint64_t cntvct = cntval - offset; + uint64_t nexttick; + + if (cpu_has_work(cs) || cntvct >= timeout) { + /* + * Don't bother to go into our "low power state" if + * we would just wake up immediately. + */ + return; + } + + if (target_el) { + env->pc -= 4; + raise_exception(env, EXCP_UDEF, syn_wfx(1, 0xe, 0, false), + target_el); + } + + if (uadd64_overflow(timeout, offset, &nexttick)) { + nexttick = UINT64_MAX; + } + if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) { + /* + * If the timeout is too long for the signed 64-bit range + * of a QEMUTimer, let it expire early. + */ + timer_mod_ns(cpu->wfxt_timer, INT64_MAX); + } else { + timer_mod(cpu->wfxt_timer, nexttick); + } + cs->exception_index = EXCP_HLT; + cs->halted = 1; + cpu_loop_exit(cs); +#endif +} + void HELPER(wfe)(CPUARMState *env) { /* This is a hint instruction that is semantically different diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 976094a5c80..591be43279c 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -1690,6 +1690,47 @@ static bool trans_WFE(DisasContext *s, arg_WFI *a) return true; } +static bool trans_WFIT(DisasContext *s, arg_WFIT *a) +{ + if (!dc_isar_feature(aa64_wfxt, s)) { + return false; + } + + /* + * Because we need to pass the register value to the helper, + * it's easier to emit the code now, unlike trans_WFI which + * defers it to aarch64_tr_tb_stop(). That means we need to + * check ss_active so that single-stepping a WFIT doesn't halt. + */ + if (s->ss_active) { + /* Act like a NOP under architectural singlestep */ + return true; + } + + gen_a64_update_pc(s, 4); + gen_helper_wfit(tcg_env, cpu_reg(s, a->rd)); + /* Go back to the main loop to check for interrupts */ + s->base.is_jmp = DISAS_EXIT; + return true; +} + +static bool trans_WFET(DisasContext *s, arg_WFET *a) +{ + if (!dc_isar_feature(aa64_wfxt, s)) { + return false; + } + + /* + * We rely here on our WFE implementation being a NOP, so we + * don't need to do anything different to handle the WFET timeout + * from what trans_WFE does. + */ + if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) { + s->base.is_jmp = DISAS_WFE; + } + return true; +} + static bool trans_XPACLRI(DisasContext *s, arg_XPACLRI *a) { if (s->pauth_active) {