From patchwork Thu Jul 16 11:34:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 51171 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C418422A28 for ; Thu, 16 Jul 2015 11:35:22 +0000 (UTC) Received: by lafd3 with SMTP id d3sf18054886laf.1 for ; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:cc:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list; bh=BICmkMxvFkeVh3TfHTHpqOTohQdIkEv9iFvD73QWMfQ=; b=l+gem0vgIuMZtr28yvi7WyxGy/Kzyl7abb1hD68QdQBuDtawwwZ7u0XfKXR7O9djaZ +7iKh3b8bt8zzSG5LT3mC4OrXOX4V/0pb2Of6zHHHtCif3hn+LeVRaXnYF1rOEadmU5Q Hf7WHNysYBIHR7TrZzocupMepc0YjGqJ2Fu/PdtvRDdR+ZnOUnGzf5FYq7hebOvgbN8s x6qi+wnIHElgqRX41ybCekNbxW9/vujrsIpmnE1tFyx9VeoEzzcodhaFZTUweg/boUDe CAjzrZ/RdF9d+OCNt1L2h85latiotzYFBmdedxFW4hR8KvHiaKwJ/KfMq967TbrKo6vF FreA== X-Gm-Message-State: ALoCoQlGEWXHcg/jh7IEKM7oG15+emx3s2PNQRjlxgNU42IZtCtCkF25TRQMTz/wHV/NlYzOQW/L X-Received: by 10.112.98.42 with SMTP id ef10mr4643985lbb.18.1437046521869; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.27.65 with SMTP id r1ls346716lag.61.gmail; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) X-Received: by 10.152.5.65 with SMTP id q1mr8933894laq.110.1437046521726; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) Received: from mail-la0-f47.google.com (mail-la0-f47.google.com. [209.85.215.47]) by mx.google.com with ESMTPS id q2si6697177laq.102.2015.07.16.04.35.21 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2015 04:35:21 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) client-ip=209.85.215.47; Received: by lahh5 with SMTP id h5so41672495lah.2 for ; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) X-Received: by 10.152.36.161 with SMTP id r1mr8905223laj.88.1437046521581; Thu, 16 Jul 2015 04:35:21 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp195413lbb; Thu, 16 Jul 2015 04:35:20 -0700 (PDT) X-Received: by 10.180.77.200 with SMTP id u8mr5979444wiw.70.1437046520044; Thu, 16 Jul 2015 04:35:20 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id gz6si13253262wjc.171.2015.07.16.04.35.19 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 16 Jul 2015 04:35:20 -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; Received: from localhost ([::1]:39670 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFhRe-0008SH-LY for patch@linaro.org; Thu, 16 Jul 2015 07:35:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58286) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFhR4-00089t-0r for qemu-devel@nongnu.org; Thu, 16 Jul 2015 07:34:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZFhQx-0001iD-Pg for qemu-devel@nongnu.org; Thu, 16 Jul 2015 07:34:41 -0400 Received: from mail-la0-f46.google.com ([209.85.215.46]:35915) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZFhQx-0001hc-ER for qemu-devel@nongnu.org; Thu, 16 Jul 2015 07:34:35 -0400 Received: by lagw2 with SMTP id w2so41648833lag.3 for ; Thu, 16 Jul 2015 04:34:33 -0700 (PDT) X-Received: by 10.152.22.99 with SMTP id c3mr9146164laf.32.1437046473737; Thu, 16 Jul 2015 04:34:33 -0700 (PDT) Received: from localhost.localdomain (0187900153.0.fullrate.dk. [2.110.55.193]) by smtp.gmail.com with ESMTPSA id at2sm1979750lbc.12.2015.07.16.04.34.32 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 16 Jul 2015 04:34:32 -0700 (PDT) From: Christoffer Dall To: qemu-devel@nongnu.org Date: Thu, 16 Jul 2015 13:34:48 +0200 Message-Id: <1437046488-10773-1-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 2.1.2.330.g565301e.dirty X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.215.46 Cc: Peter Maydell , Marc Zyngier , Claudio Fontana , Jan Kiszka , kvmarm@lists.cs.columbia.edu, Christoffer Dall Subject: [Qemu-devel] [PATCH v2] target-arm: kvm: Differentiate registers based on write-back levels X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 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 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: christoffer.dall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Some registers like the CNTVCT register should only be written to the kernel as part of machine initialization or on vmload operations, but never during runtime, as this can potentially make time go backwards or create inconsistent time observations between VCPUs. Introduce a list of registers that should not be written back at runtime and check this list on syncing the register state to the KVM state. Signed-off-by: Christoffer Dall --- Changes since RFC: - Move cpreg_level to kvm_arm_cpreg_level and into kvm32.c and kvm64.c - Changed struct name and declare as static const dtc | 2 +- target-arm/kvm.c | 6 +++++- target-arm/kvm32.c | 30 +++++++++++++++++++++++++++++- target-arm/kvm64.c | 30 +++++++++++++++++++++++++++++- target-arm/kvm_arm.h | 12 +++++++++++- target-arm/machine.c | 2 +- 6 files changed, 76 insertions(+), 6 deletions(-) diff --git a/dtc b/dtc index 65cc4d2..bc895d6 160000 --- a/dtc +++ b/dtc @@ -1 +1 @@ -Subproject commit 65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf +Subproject commit bc895d6d09695d05ceb8b52486ffe861d6cfbdde diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 548bfd7..b278542 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -409,7 +409,7 @@ bool write_kvmstate_to_list(ARMCPU *cpu) return ok; } -bool write_list_to_kvmstate(ARMCPU *cpu) +bool write_list_to_kvmstate(ARMCPU *cpu, int level) { CPUState *cs = CPU(cpu); int i; @@ -421,6 +421,10 @@ bool write_list_to_kvmstate(ARMCPU *cpu) uint32_t v32; int ret; + if (kvm_arm_cpreg_level(regidx) > level) { + continue; + } + r.id = regidx; switch (regidx & KVM_REG_SIZE_MASK) { case KVM_REG_SIZE_U32: diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index d7e7d68..6769815 100644 --- a/target-arm/kvm32.c +++ b/target-arm/kvm32.c @@ -153,6 +153,34 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) } } +typedef struct CPRegStateLevel { + uint64_t regidx; + int level; +} CPRegStateLevel; + +/* All coprocessor registers not listed in the following table are assumed to + * be of the level KVM_PUT_RUNTIME_STATE, a register should be written less + * often, you must add it to this table with a state of either + * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE. + */ +static const CPRegStateLevel non_runtime_cpregs[] = { + { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE }, +}; + +int kvm_arm_cpreg_level(uint64_t regidx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) { + const CPRegStateLevel *l = &non_runtime_cpregs[i]; + if (l->regidx == regidx) { + return l->level; + } + } + + return KVM_PUT_RUNTIME_STATE; +} + #define ARM_MPIDR_HWID_BITMASK 0xFFFFFF #define ARM_CPU_ID_MPIDR 0, 0, 0, 5 @@ -367,7 +395,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) * managed to update the CPUARMState with, and only allowing those * to be written back up into the kernel). */ - if (!write_list_to_kvmstate(cpu)) { + if (!write_list_to_kvmstate(cpu, level)) { return EINVAL; } diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index ac34f51..d59f41c 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -139,6 +139,34 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) } } +typedef struct CPRegStateLevel { + uint64_t regidx; + int level; +} CPRegStateLevel; + +/* All system not listed in the following table are assumed to be of the level + * KVM_PUT_RUNTIME_STATE, a register should be written less often, you must + * add it to this table with a state of either KVM_PUT_RESET_STATE or + * KVM_PUT_FULL_STATE. + */ +static const CPRegStateLevel non_runtime_cpregs[] = { + { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE }, +}; + +int kvm_arm_cpreg_level(uint64_t regidx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) { + const CPRegStateLevel *l = &non_runtime_cpregs[i]; + if (l->regidx == regidx) { + return l->level; + } + } + + return KVM_PUT_RUNTIME_STATE; +} + #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x)) @@ -280,7 +308,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) return ret; } - if (!write_list_to_kvmstate(cpu)) { + if (!write_list_to_kvmstate(cpu, level)) { return EINVAL; } diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h index 5abd591..7912d74 100644 --- a/target-arm/kvm_arm.h +++ b/target-arm/kvm_arm.h @@ -69,8 +69,18 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu); bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); /** + * kvm_arm_cpreg_level + * regidx: KVM register index + * + * Return the level of this coprocessor/system register. Return value is + * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. + */ +int kvm_arm_cpreg_level(uint64_t regidx); + +/** * write_list_to_kvmstate: * @cpu: ARMCPU + * @level: the state level to sync * * For each register listed in the ARMCPU cpreg_indexes list, write * its value from the cpreg_values list into the kernel (via ioctl). @@ -83,7 +93,7 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); * Note that we do not stop early on failure -- we will attempt * writing all registers in the list. */ -bool write_list_to_kvmstate(ARMCPU *cpu); +bool write_list_to_kvmstate(ARMCPU *cpu, int level); /** * write_kvmstate_to_list: diff --git a/target-arm/machine.c b/target-arm/machine.c index 9eb51df..32adfe7 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -251,7 +251,7 @@ static int cpu_post_load(void *opaque, int version_id) } if (kvm_enabled()) { - if (!write_list_to_kvmstate(cpu)) { + if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) { return -1; } /* Note that it's OK for the TCG side not to know about