From patchwork Tue Jul 21 11:17:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 51301 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f197.google.com (mail-lb0-f197.google.com [209.85.217.197]) by patches.linaro.org (Postfix) with ESMTPS id 745D220323 for ; Tue, 21 Jul 2015 11:18:07 +0000 (UTC) Received: by lbvb1 with SMTP id b1sf46584434lbv.3 for ; Tue, 21 Jul 2015 04:18:06 -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:in-reply-to:references: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=eEWTE3Rc/PdeqL9akBp50cqCBrpx6DHH+wL7hvu3+uQ=; b=Lyhc1D02+8Lo1vJvu7XSswqHWcFD7YMZ7X8Kmv5qVpZkx4b5Ok0kgcB3GEaFtktvrv fcOrHB1VlbDV02aP8IiuCFh8iBaRx9AX/CY73xCQRbuqrMg/RKuvdxJsLTsTnzluevtl GSZd8ehIgLujZYgXb8dUEmhcEtHhNwK2phFdTrE32vTvoMOoLg08Wus413q2ifnWlaSY a7+x5pyahHlCT9iTgfxoilB5BvgeqKTNImLSTvMa2xYnNsTUsrHUMZzbkCMUbdHeWmYc 4c5wNcqnQ1wNoAqYhi+MGzsf6pdb0MOszJABVEbD7yB2TgtQb5ONAmIoRw8dPY959wdF pFPw== X-Gm-Message-State: ALoCoQmMwAW8ZLOK1HALbicUFFS8bF4jn33cWNQj4y4U4pkbLwIcanA7ybOMs2HXLP/ENjN/nq6F X-Received: by 10.180.11.226 with SMTP id t2mr8789813wib.0.1437477486442; Tue, 21 Jul 2015 04:18:06 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.21.230 with SMTP id y6ls966476lae.20.gmail; Tue, 21 Jul 2015 04:18:06 -0700 (PDT) X-Received: by 10.152.43.134 with SMTP id w6mr29231747lal.120.1437477486268; Tue, 21 Jul 2015 04:18:06 -0700 (PDT) Received: from mail-lb0-f180.google.com (mail-lb0-f180.google.com. [209.85.217.180]) by mx.google.com with ESMTPS id w7si20490889law.111.2015.07.21.04.18.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Jul 2015 04:18:06 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.180 as permitted sender) client-ip=209.85.217.180; Received: by lbbzr7 with SMTP id zr7so113507509lbb.1 for ; Tue, 21 Jul 2015 04:18:06 -0700 (PDT) X-Received: by 10.152.5.228 with SMTP id v4mr32389278lav.36.1437477486117; Tue, 21 Jul 2015 04:18:06 -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.7.198 with SMTP id l6csp1371078lba; Tue, 21 Jul 2015 04:18:05 -0700 (PDT) X-Received: by 10.194.57.232 with SMTP id l8mr18020683wjq.48.1437477483622; Tue, 21 Jul 2015 04:18:03 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id ed5si18512535wib.67.2015.07.21.04.18.03 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 21 Jul 2015 04:18:03 -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]:58750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHVYg-0005Tp-4O for patch@linaro.org; Tue, 21 Jul 2015 07:18:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35797) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHVXx-0004fI-09 for qemu-devel@nongnu.org; Tue, 21 Jul 2015 07:17:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZHVXv-0000rr-9x for qemu-devel@nongnu.org; Tue, 21 Jul 2015 07:17:16 -0400 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:34674) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHVXv-0000kL-0e for qemu-devel@nongnu.org; Tue, 21 Jul 2015 07:17:15 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1ZHVXn-0001Dd-G9 for qemu-devel@nongnu.org; Tue, 21 Jul 2015 12:17:07 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Tue, 21 Jul 2015 12:17:06 +0100 Message-Id: <1437477427-4656-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1437477427-4656-1-git-send-email-peter.maydell@linaro.org> References: <1437477427-4656-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 1/2] 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: peter.maydell@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.217.180 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 From: Christoffer Dall 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 Message-id: 1437046488-10773-1-git-send-email-christoffer.dall@linaro.org [PMM: tweaked a few comments, added the new argument to the stub write_list_to_kvmstate() in target-arm/kvm-stub.c] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/kvm-stub.c | 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/target-arm/kvm-stub.c b/target-arm/kvm-stub.c index cd1849f..db2edc2 100644 --- a/target-arm/kvm-stub.c +++ b/target-arm/kvm-stub.c @@ -17,7 +17,7 @@ bool write_kvmstate_to_list(ARMCPU *cpu) abort(); } -bool write_list_to_kvmstate(ARMCPU *cpu) +bool write_list_to_kvmstate(ARMCPU *cpu, int level) { abort(); } 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..421ce0e 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. If 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..bd60889 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 registers not listed in the following table are assumed to be + * of the level KVM_PUT_RUNTIME_STATE. If 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