From patchwork Wed Aug 4 08:57:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418115 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65A09C4320A for ; Wed, 4 Aug 2021 08:58:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41E5960F6F for ; Wed, 4 Aug 2021 08:58:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236775AbhHDI6t (ORCPT ); Wed, 4 Aug 2021 04:58:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6t (ORCPT ); Wed, 4 Aug 2021 04:58:49 -0400 Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE5C0C0613D5 for ; Wed, 4 Aug 2021 01:58:36 -0700 (PDT) Received: by mail-qk1-x74a.google.com with SMTP id h5-20020a05620a0525b02903b861bec838so1675771qkh.7 for ; Wed, 04 Aug 2021 01:58:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=9z0ILel/nmHkGUMptTPmpCG4j9f031MAvczP47Mkt78=; b=AGG526CClu6IqHFTOxS7+h3HvPWXLqKYwyxWDqhy8O1Cl7kRhpnrrXFTY0kzLPlJzo NTLuHbzcLYaYfAWrM32xY1DL6EHrQH4/2lErBCn8/ZGON8Be4/Pp9eWnRrHfI5ABkk+e cUAX5/1tP6hG7xgE0KZ69uOsXKCWECXSJndhcqwqutNTyGslSd/lvGhdMfdY1YZV67+W DWELveZd0WTMUmICxJLUctfDxryaN/y9+D66dBcuvb4CitoE5kvYTWemb+5QNRxgHI0j rWPx8EeySutkqhAJYHR/vC6ZOVzwZ3vF7onQk6tkqzA+Opb0I7MhtY7K0lwaz97Zb10g jtsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=9z0ILel/nmHkGUMptTPmpCG4j9f031MAvczP47Mkt78=; b=d3nLXgq65fk8fK4/0O7KJb0D35lEuye0/l73Ue2gYrLBhlrJ51Yqjya1IUn6IsH6yj BKfvaUcocuA/b61JTYBrA0avFiLcGfZYkXE2OqX0/yO6KAtEpCpb3X00iRXAXxl1lHwV EPoHrip4xXzkpU8SgGvgvdtc1F3PcKTA/SRtO8Hf9G5QOffCuiKbfsYTl7Ca3nL3qR4o o8DVBFtZwJkftP8lmNn2Wy4d/nH+9w5HIHzeQjoQ+E6gGmCTS/AdFOBB62Z/c942gbne aZ53noa9bWTX4RerWtlhNr+8sjCtOWp8E+cNSOPUY1xzDCexvAv+vmpvvTYVhCyzGyEv 470g== X-Gm-Message-State: AOAM531WyOpRYwwCuy4/TNr++fqVxTnVXCm8XnAqZbvJjoFpoMsWRjg7 U21tl/ykLBV+0zEF0Rn6msGvSQbDoPyS+SPh3vF9iMqy2BtUnw2xhc3C3jpM7W4nj47AyZerKES k5qYrRH2pgzbMKoLQiG8eHhYljxpgoRRFtC1l9/VDlHc9ZuqqsfEIgEc4Uw== X-Google-Smtp-Source: ABdhPJzxzqd5PN7eP88ZrBpXcJ5Qw54s+lcbwp2wfv6KXhmpgwkZOP22ITfr7gZ3p1xKgG6E9IZ8pxMUSks= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6214:332:: with SMTP id j18mr25863430qvu.21.1628067515916; Wed, 04 Aug 2021 01:58:35 -0700 (PDT) Date: Wed, 4 Aug 2021 08:57:59 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-2-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 01/21] KVM: x86: Fix potential race in KVM_GET_CLOCK From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Sean noticed that KVM_GET_CLOCK was checking kvm_arch.use_master_clock outside of the pvclock sync lock. This is problematic, as the clock value written to the user may or may not actually correspond to a stable TSC. Fix the race by populating the entire kvm_clock_data structure behind the pvclock_gtod_sync_lock. Suggested-by: Sean Christopherson Signed-off-by: Oliver Upton Signed-off-by: Paolo Bonzini Reviewed-by: Oliver Upton --- arch/x86/kvm/x86.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8cdf4ac6990b..34287c522f4e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2782,19 +2782,20 @@ static void kvm_gen_update_masterclock(struct kvm *kvm) #endif } -u64 get_kvmclock_ns(struct kvm *kvm) +static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data) { struct kvm_arch *ka = &kvm->arch; struct pvclock_vcpu_time_info hv_clock; unsigned long flags; - u64 ret; spin_lock_irqsave(&ka->pvclock_gtod_sync_lock, flags); if (!ka->use_master_clock) { spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); - return get_kvmclock_base_ns() + ka->kvmclock_offset; + data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset; + return; } + data->flags |= KVM_CLOCK_TSC_STABLE; hv_clock.tsc_timestamp = ka->master_cycle_now; hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); @@ -2806,13 +2807,26 @@ u64 get_kvmclock_ns(struct kvm *kvm) kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, &hv_clock.tsc_shift, &hv_clock.tsc_to_system_mul); - ret = __pvclock_read_cycles(&hv_clock, rdtsc()); - } else - ret = get_kvmclock_base_ns() + ka->kvmclock_offset; + data->clock = __pvclock_read_cycles(&hv_clock, rdtsc()); + } else { + data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset; + } put_cpu(); +} - return ret; +u64 get_kvmclock_ns(struct kvm *kvm) +{ + struct kvm_clock_data data; + + /* + * Zero flags as it's accessed RMW, leave everything else uninitialized + * as clock is always written and no other fields are consumed. + */ + data.flags = 0; + + get_kvmclock(kvm, &data); + return data.clock; } static void kvm_setup_pvclock_page(struct kvm_vcpu *v, @@ -6104,11 +6118,14 @@ long kvm_arch_vm_ioctl(struct file *filp, } case KVM_GET_CLOCK: { struct kvm_clock_data user_ns; - u64 now_ns; - now_ns = get_kvmclock_ns(kvm); - user_ns.clock = now_ns; - user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0; + /* + * Zero flags as it is accessed RMW, leave everything else + * uninitialized as clock is always written and no other fields + * are consumed. + */ + user_ns.flags = 0; + get_kvmclock(kvm, &user_ns); memset(&user_ns.pad, 0, sizeof(user_ns.pad)); r = -EFAULT; From patchwork Wed Aug 4 08:58:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418119 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4DD61C4338F for ; Wed, 4 Aug 2021 08:58:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 53CE260FC3 for ; Wed, 4 Aug 2021 08:58:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236801AbhHDI6u (ORCPT ); Wed, 4 Aug 2021 04:58:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6u (ORCPT ); Wed, 4 Aug 2021 04:58:50 -0400 Received: from mail-io1-xd49.google.com (mail-io1-xd49.google.com [IPv6:2607:f8b0:4864:20::d49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D8A48C0613D5 for ; Wed, 4 Aug 2021 01:58:37 -0700 (PDT) Received: by mail-io1-xd49.google.com with SMTP id p7-20020a6b63070000b02904f58bb90366so1048348iog.14 for ; Wed, 04 Aug 2021 01:58:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=K7pLZDgIPuV12HPJ9thky4TOXLt6Z7al5u7GtuvUBZA=; b=by4LiJhYPpMwogtLXJ7fjEm8BONAI58MOYgbyTmmvv9mv9oTtLGatcNERorAuv0dmW UC3XjcBEb+sx3noaVxjS+QVNRj+biM3Lo1eV/RlruKJ50GC+iadfF6aaHguozUNiI3b8 YVhEsnwcNXmmJJqaEt39Vf/k1B6m654tV9mllpPUiOfRIYnAY37fY/gsmCSkNxueDDY4 CHN0wKT96CZGFhb8xqQkHDHbLL8+lrMg5+vDb+3rcZNwb2534M5p+W2BHQjONV2mDibP t5YC7m8i/+Un2HWG0r/tiICiXyhzpxJRCRei0WxRWZFxrCaI8v+wY5+1CvTYu5q7gqWn QVGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=K7pLZDgIPuV12HPJ9thky4TOXLt6Z7al5u7GtuvUBZA=; b=qNMo8/5Lj1dZ8RvV9qKXr935185BTeFD44RXIT6A5Fh32BK5RFOGbc+9NqYRc35EPM dgpI3wVlZjYd3AqSNo8KYw/p8xe/E1Ptp7os+KqPptaHabngoaUKisEENsWLBRY5hCUE 96FcWgIj+uALbnEFhNLgVOG7advdWMIOPQKNKzIKEvDbg4qkF+yeZ/g5ZiY4mGeZBZxm 4VseUcMUAZksw/DaP6vVVTAIB9v7m/eMB6RyQ/9og0qQd/W32oI0Gak7RGh41YUepcnF YdnvuGNPMLAyjJmsndG5WmrDn9vBHPboON8r3EUvCq3rAeC4cbzO1pzu+V1OHSZdOsLD pv2g== X-Gm-Message-State: AOAM532UxjomMFpGGlYtPec3SID4EtU/meipJd9xNw1ubw/OYOjFphhG 0D2qh8zFQwHc1N34B0Hlk/uEq6jvAUC7V5x7rdszG4Fd3DPGeSvw9Z2fbJO8fQJRkJjeIJlEzxL Vsz6sBCOYwG8TyHOOxZ51/oDwWBjhBoOGwAo/R7xrnwm8GL8ooedepbWxbQ== X-Google-Smtp-Source: ABdhPJz2W1LC0u615gdgeVlOBMaE1ErBs2fgBK7IpnYekTHQRjIlezwcsg27qu68TXmnKqnX9nsOS4p49MQ= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a5d:824e:: with SMTP id n14mr394806ioo.134.1628067517220; Wed, 04 Aug 2021 01:58:37 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:00 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-3-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 02/21] KVM: x86: Report host tsc and realtime values in KVM_GET_CLOCK From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Handling the migration of TSCs correctly is difficult, in part because Linux does not provide userspace with the ability to retrieve a (TSC, realtime) clock pair for a single instant in time. In lieu of a more convenient facility, KVM can report similar information in the kvm_clock structure. Provide userspace with a host TSC & realtime pair iff the realtime clock is based on the TSC. If userspace provides KVM_SET_CLOCK with a valid realtime value, advance the KVM clock by the amount of elapsed time. Do not step the KVM clock backwards, though, as it is a monotonic oscillator. Suggested-by: Paolo Bonzini Signed-off-by: Oliver Upton --- Documentation/virt/kvm/api.rst | 42 ++++++++--- arch/x86/include/asm/kvm_host.h | 3 + arch/x86/kvm/x86.c | 127 ++++++++++++++++++-------------- include/uapi/linux/kvm.h | 7 +- 4 files changed, 112 insertions(+), 67 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index dae68e68ca23..8d4a3471ad9e 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -993,20 +993,34 @@ such as migration. When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the set of bits that KVM can return in struct kvm_clock_data's flag member. -The only flag defined now is KVM_CLOCK_TSC_STABLE. If set, the returned -value is the exact kvmclock value seen by all VCPUs at the instant -when KVM_GET_CLOCK was called. If clear, the returned value is simply -CLOCK_MONOTONIC plus a constant offset; the offset can be modified -with KVM_SET_CLOCK. KVM will try to make all VCPUs follow this clock, -but the exact value read by each VCPU could differ, because the host -TSC is not stable. +FLAGS: + +KVM_CLOCK_TSC_STABLE. If set, the returned value is the exact kvmclock +value seen by all VCPUs at the instant when KVM_GET_CLOCK was called. +If clear, the returned value is simply CLOCK_MONOTONIC plus a constant +offset; the offset can be modified with KVM_SET_CLOCK. KVM will try +to make all VCPUs follow this clock, but the exact value read by each +VCPU could differ, because the host TSC is not stable. + +KVM_CLOCK_REALTIME. If set, the `realtime` field in the kvm_clock_data +structure is populated with the value of the host's real time +clocksource at the instant when KVM_GET_CLOCK was called. If clear, +the `realtime` field does not contain a value. + +KVM_CLOCK_HOST_TSC. If set, the `host_tsc` field in the kvm_clock_data +structure is populated with the value of the host's timestamp counter (TSC) +at the instant when KVM_GET_CLOCK was called. If clear, the `host_tsc` field +does not contain a value. :: struct kvm_clock_data { __u64 clock; /* kvmclock current value */ __u32 flags; - __u32 pad[9]; + __u32 pad0; + __u64 realtime; + __u64 host_tsc; + __u32 pad[4]; }; @@ -1023,12 +1037,22 @@ Sets the current timestamp of kvmclock to the value specified in its parameter. In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios such as migration. +FLAGS: + +KVM_CLOCK_REALTIME. If set, KVM will compare the value of the `realtime` field +with the value of the host's real time clocksource at the instant when +KVM_SET_CLOCK was called. The difference in elapsed time is added to the final +kvmclock value that will be provided to guests. + :: struct kvm_clock_data { __u64 clock; /* kvmclock current value */ __u32 flags; - __u32 pad[9]; + __u32 pad0; + __u64 realtime; + __u64 host_tsc; + __u32 pad[4]; }; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 6818095dd157..d6376ca8efce 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1926,4 +1926,7 @@ int kvm_cpu_dirty_log_size(void); int alloc_all_memslots_rmaps(struct kvm *kvm); +#define KVM_CLOCK_VALID_FLAGS \ + (KVM_CLOCK_TSC_STABLE | KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC) + #endif /* _ASM_X86_KVM_HOST_H */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 34287c522f4e..26f1fa263192 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2804,10 +2804,20 @@ static void get_kvmclock(struct kvm *kvm, struct kvm_clock_data *data) get_cpu(); if (__this_cpu_read(cpu_tsc_khz)) { +#ifdef CONFIG_X86_64 + struct timespec64 ts; + + if (kvm_get_walltime_and_clockread(&ts, &data->host_tsc)) { + data->realtime = ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec; + data->flags |= KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC; + } else +#endif + data->host_tsc = rdtsc(); + kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, &hv_clock.tsc_shift, &hv_clock.tsc_to_system_mul); - data->clock = __pvclock_read_cycles(&hv_clock, rdtsc()); + data->clock = __pvclock_read_cycles(&hv_clock, data->host_tsc); } else { data->clock = get_kvmclock_base_ns() + ka->kvmclock_offset; } @@ -4047,7 +4057,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = KVM_SYNC_X86_VALID_FIELDS; break; case KVM_CAP_ADJUST_CLOCK: - r = KVM_CLOCK_TSC_STABLE; + r = KVM_CLOCK_VALID_FLAGS; break; case KVM_CAP_X86_DISABLE_EXITS: r |= KVM_X86_DISABLE_EXITS_HLT | KVM_X86_DISABLE_EXITS_PAUSE | @@ -5834,6 +5844,60 @@ int kvm_arch_pm_notifier(struct kvm *kvm, unsigned long state) } #endif /* CONFIG_HAVE_KVM_PM_NOTIFIER */ +static int kvm_vm_ioctl_get_clock(struct kvm *kvm, void __user *argp) +{ + struct kvm_clock_data data; + + memset(&data, 0, sizeof(data)); + get_kvmclock(kvm, &data); + + if (copy_to_user(argp, &data, sizeof(data))) + return -EFAULT; + + return 0; +} + +static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void __user *argp) +{ + struct kvm_arch *ka = &kvm->arch; + struct kvm_clock_data data; + u64 now_raw_ns; + + if (copy_from_user(&data, argp, sizeof(data))) + return -EFAULT; + + if (data.flags & ~KVM_CLOCK_REALTIME) + return -EINVAL; + + /* + * TODO: userspace has to take care of races with VCPU_RUN, so + * kvm_gen_update_masterclock() can be cut down to locked + * pvclock_update_vm_gtod_copy(). + */ + kvm_gen_update_masterclock(kvm); + + spin_lock_irq(&ka->pvclock_gtod_sync_lock); + if (data.flags & KVM_CLOCK_REALTIME) { + u64 now_real_ns = ktime_get_real_ns(); + + /* + * Avoid stepping the kvmclock backwards. + */ + if (now_real_ns > data.realtime) + data.clock += now_real_ns - data.realtime; + } + + if (ka->use_master_clock) + now_raw_ns = ka->master_kernel_ns; + else + now_raw_ns = get_kvmclock_base_ns(); + ka->kvmclock_offset = data.clock - now_raw_ns; + spin_unlock_irq(&ka->pvclock_gtod_sync_lock); + + kvm_make_all_cpus_request(kvm, KVM_REQ_CLOCK_UPDATE); + return 0; +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -6077,63 +6141,12 @@ long kvm_arch_vm_ioctl(struct file *filp, break; } #endif - case KVM_SET_CLOCK: { - struct kvm_arch *ka = &kvm->arch; - struct kvm_clock_data user_ns; - u64 now_ns; - - r = -EFAULT; - if (copy_from_user(&user_ns, argp, sizeof(user_ns))) - goto out; - - r = -EINVAL; - if (user_ns.flags) - goto out; - - r = 0; - /* - * TODO: userspace has to take care of races with VCPU_RUN, so - * kvm_gen_update_masterclock() can be cut down to locked - * pvclock_update_vm_gtod_copy(). - */ - kvm_gen_update_masterclock(kvm); - - /* - * This pairs with kvm_guest_time_update(): when masterclock is - * in use, we use master_kernel_ns + kvmclock_offset to set - * unsigned 'system_time' so if we use get_kvmclock_ns() (which - * is slightly ahead) here we risk going negative on unsigned - * 'system_time' when 'user_ns.clock' is very small. - */ - spin_lock_irq(&ka->pvclock_gtod_sync_lock); - if (kvm->arch.use_master_clock) - now_ns = ka->master_kernel_ns; - else - now_ns = get_kvmclock_base_ns(); - ka->kvmclock_offset = user_ns.clock - now_ns; - spin_unlock_irq(&ka->pvclock_gtod_sync_lock); - - kvm_make_all_cpus_request(kvm, KVM_REQ_CLOCK_UPDATE); + case KVM_SET_CLOCK: + r = kvm_vm_ioctl_set_clock(kvm, argp); break; - } - case KVM_GET_CLOCK: { - struct kvm_clock_data user_ns; - - /* - * Zero flags as it is accessed RMW, leave everything else - * uninitialized as clock is always written and no other fields - * are consumed. - */ - user_ns.flags = 0; - get_kvmclock(kvm, &user_ns); - memset(&user_ns.pad, 0, sizeof(user_ns.pad)); - - r = -EFAULT; - if (copy_to_user(argp, &user_ns, sizeof(user_ns))) - goto out; - r = 0; + case KVM_GET_CLOCK: + r = kvm_vm_ioctl_get_clock(kvm, argp); break; - } case KVM_MEMORY_ENCRYPT_OP: { r = -ENOTTY; if (kvm_x86_ops.mem_enc_op) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index d9e4aabcb31a..53a49cb8616a 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1223,11 +1223,16 @@ struct kvm_irqfd { /* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */ #define KVM_CLOCK_TSC_STABLE 2 +#define KVM_CLOCK_REALTIME (1 << 2) +#define KVM_CLOCK_HOST_TSC (1 << 3) struct kvm_clock_data { __u64 clock; __u32 flags; - __u32 pad[9]; + __u32 pad0; + __u64 realtime; + __u64 host_tsc; + __u32 pad[4]; }; /* For KVM_CAP_SW_TLB */ From patchwork Wed Aug 4 08:58:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418117 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 507FEC432BE for ; Wed, 4 Aug 2021 08:58:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2827D60F56 for ; Wed, 4 Aug 2021 08:58:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236811AbhHDI6v (ORCPT ); Wed, 4 Aug 2021 04:58:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6v (ORCPT ); Wed, 4 Aug 2021 04:58:51 -0400 Received: from mail-il1-x149.google.com (mail-il1-x149.google.com [IPv6:2607:f8b0:4864:20::149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DC06EC0613D5 for ; Wed, 4 Aug 2021 01:58:38 -0700 (PDT) Received: by mail-il1-x149.google.com with SMTP id c7-20020a928e070000b0290222cccb8651so609862ild.14 for ; Wed, 04 Aug 2021 01:58:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=yT+nCrFmg471JgKctqrSQtIm1tfSoSdZEimBbuaP3hM=; b=I75O/UznjRurZ12yqjeSXM1uRHLtkMyqOHMPWxjHv7EqFHpdUtNM/q2lhH3rSJRXMi hmtx2v5DfPRntVTXd1HEnfhKFNm++uRppRctqQ9/tBN3y/qLQO6G3I2+zHRVMWwO1Qei zrOEuyl5E91LBxGmWuvw3x7WRXMvdLPIXIO7e3es+i3ueOVQhqmLhiWEr19ExFdGTomd tzU7TnghJPoMZ486oD2ZRvoEOyvto0wtqL/JmqdjzcDUWMzObugg/StxuiD9e42u0kek tBdoapOnjPK+cQ9upIllnUwqm+zBJQdTCWl7xwGMM/2Q+sZLNygYgEiJoxOxk2TjKJ7l qk2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=yT+nCrFmg471JgKctqrSQtIm1tfSoSdZEimBbuaP3hM=; b=JvprzMpG1xfcxSHu8jSMuu7HcH+bZIPUc0adzqugszAoVzeB3GRlLKGMjovYnP0se2 EEiwd4t0UeoJMg52Vs8PJ+NDhljAKzcbLPCHkkhjuo0G/znJMOxgZf4FDd9Z9qUKYmbN t2RABQMAovyyEXWeKsLTzrXljNJ3o2VbVfA9cNHL4OCvYTO7Btvo2yhscfgzWImBgnlb 52dCwiJJQ0MJpOVbcJ29WCRMDrsTuwteMHbLCTj46ZRTH968/4xHsfKjEQ5UYOHqFvGM gcvStgJwk3siIczV1xyXdGguRW3af4s+NFK9vbF9w5tXu7tQQj+knPdyAwf9WEe4ziLo CudA== X-Gm-Message-State: AOAM533PckNERgFJus118+f5eGDOX7Bw64QQ7yHv1ZynUeGZD5JH7V9i 1m4x2LOEC+UC5ob/Klq1zYDP9C5sDprQwn+I3prP60W+4fwqnAiB8QA89Xe82c3Q6Rwt0yomqi+ GrauGil5fNHn8Hp2cfeI37IwitVtXppUF22jXr46KmWpGCcyGo1T+LJunfw== X-Google-Smtp-Source: ABdhPJxSOYTpnXMnEgvD536Lr//pppHFulfycmnTBjxZ233HWebGAqoEW5FBilAhV/Yot+rrAUs5jGbPkWM= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a92:cf44:: with SMTP id c4mr262704ilr.11.1628067518129; Wed, 04 Aug 2021 01:58:38 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:01 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-4-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 03/21] KVM: x86: Take the pvclock sync lock behind the tsc_write_lock From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org A later change requires that the pvclock sync lock be taken while holding the tsc_write_lock. Change the locking in kvm_synchronize_tsc() to align with the requirement to isolate the locking change to its own commit. Cc: Sean Christopherson Signed-off-by: Oliver Upton --- Documentation/virt/kvm/locking.rst | 11 +++++++++++ arch/x86/kvm/x86.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/locking.rst b/Documentation/virt/kvm/locking.rst index 8138201efb09..0bf346adac2a 100644 --- a/Documentation/virt/kvm/locking.rst +++ b/Documentation/virt/kvm/locking.rst @@ -36,6 +36,9 @@ On x86: holding kvm->arch.mmu_lock (typically with ``read_lock``, otherwise there's no need to take kvm->arch.tdp_mmu_pages_lock at all). +- kvm->arch.tsc_write_lock is taken outside + kvm->arch.pvclock_gtod_sync_lock + Everything else is a leaf: no other lock is taken inside the critical sections. @@ -222,6 +225,14 @@ time it will be set using the Dirty tracking mechanism described above. :Comment: 'raw' because hardware enabling/disabling must be atomic /wrt migration. +:Name: kvm_arch::pvclock_gtod_sync_lock +:Type: raw_spinlock_t +:Arch: x86 +:Protects: kvm_arch::{cur_tsc_generation,cur_tsc_nsec,cur_tsc_write, + cur_tsc_offset,nr_vcpus_matched_tsc} +:Comment: 'raw' because updating the kvm master clock must not be + preempted. + :Name: kvm_arch::tsc_write_lock :Type: raw_spinlock :Arch: x86 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 26f1fa263192..93b449761fbe 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2529,7 +2529,6 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write; kvm_vcpu_write_tsc_offset(vcpu, offset); - raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); spin_lock_irqsave(&kvm->arch.pvclock_gtod_sync_lock, flags); if (!matched) { @@ -2540,6 +2539,7 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) kvm_track_tsc_matching(vcpu); spin_unlock_irqrestore(&kvm->arch.pvclock_gtod_sync_lock, flags); + raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); } static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, From patchwork Wed Aug 4 08:58:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418121 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B017C4320A for ; Wed, 4 Aug 2021 08:58:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6CDF661037 for ; Wed, 4 Aug 2021 08:58:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236816AbhHDI6w (ORCPT ); Wed, 4 Aug 2021 04:58:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6w (ORCPT ); Wed, 4 Aug 2021 04:58:52 -0400 Received: from mail-il1-x14a.google.com (mail-il1-x14a.google.com [IPv6:2607:f8b0:4864:20::14a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCC2FC061798 for ; Wed, 4 Aug 2021 01:58:39 -0700 (PDT) Received: by mail-il1-x14a.google.com with SMTP id c20-20020a9294140000b02902141528bc7cso624017ili.3 for ; Wed, 04 Aug 2021 01:58:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=uloEpvDC1x4KyjcHtp66tRD4W6eFcIbVLp7KXwjdRug=; b=wWYNfr0/AgyWtA0xf6ApJcYYykZozz9WwRpQ2OdZvKK6Nt5sdWxU7SXTd0G4pRobA3 +iF6vlIXzYig3jrnte3drl3CENUMZinaVvksioh27z6Ierrhvj2stjn6tx5duzEGuwuS yprkj51j3QUNbZF2ZFzngnBUD1Gr6Ph5TxERYyOUfzqWsNTutgKpCpPgdX28ctqVcJk7 LJjiO42DBcrzWRLU4GB2GWmPqKgL7AYzmO5hk54ey9J6OoFr96x/KSAF1JHTyQtOZSJh mPHrSOeRaBFaCWmL1z7NLA5uURwVEfaz5ccXJRo10iLCVu+DzEqBDvrjAnY1N68Fsyui /wEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=uloEpvDC1x4KyjcHtp66tRD4W6eFcIbVLp7KXwjdRug=; b=d6If2TEOCqass2eCzR6j2Hbz1VVncrzDaDxuHcu2ek9KJk1v4wlBvoyq5biXJ3at9/ zLkTm3I994HDHFSqEE9AFw1g29JBsGaAmd27c/VqEyhB+RwMXve1VU29qzECrq5f1r1x 6hC98wVpzidMlPX0Vp7Z1X02WG/i+sF+6ZitwaEvFWuEajAAU91ld36/llb4hT0C8ibJ xk82ioRJonbAkaArqoVCvJ+5yoAUpjX7yCA9M2d1X6KPzVEUPA/1m2jb3bPIML7kBmgj ogVHIOqInhCzUXVXno60ABDp0afbW/pT9n7mbdGy4dfFGLDAzIRveEDd4kafSfi1dQ7y FTMQ== X-Gm-Message-State: AOAM530Ulla0gHpl1Jg83DMJgdmTVT8+qyzJC0/ec4g/Lkrl75GMn3fx ZzIiEKuKJfrNzUCoR3ao/R89O8yDiPb+J93nrysvY8OJ3QPkG/VWBaYGn7MLVptzao/5QEhFyZW MdK4iv67nn0JN0QzfjqpIs/18junCwCEokyRn3iQ5hnwrWHTIvaQgmHXuVw== X-Google-Smtp-Source: ABdhPJwtVZyUWoHKFbiNQ2h2t9X7r0uhYjdaRL+9QGByuYY9K8DV9KrSpRwCNZjrwBRQxEPOiczXInUogDA= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6638:381e:: with SMTP id i30mr23084938jav.17.1628067519135; Wed, 04 Aug 2021 01:58:39 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:02 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-5-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 04/21] KVM: x86: Refactor tsc synchronization code From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Refactor kvm_synchronize_tsc to make a new function that allows callers to specify TSC parameters (offset, value, nanoseconds, etc.) explicitly for the sake of participating in TSC synchronization. Signed-off-by: Oliver Upton --- arch/x86/kvm/x86.c | 105 ++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 93b449761fbe..91aea751d621 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2443,13 +2443,71 @@ static inline bool kvm_check_tsc_unstable(void) return check_tsc_unstable(); } +/* + * Infers attempts to synchronize the guest's tsc from host writes. Sets the + * offset for the vcpu and tracks the TSC matching generation that the vcpu + * participates in. + */ +static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc, + u64 ns, bool matched) +{ + struct kvm *kvm = vcpu->kvm; + bool already_matched; + + lockdep_assert_held(&kvm->arch.tsc_write_lock); + + already_matched = + (vcpu->arch.this_tsc_generation == kvm->arch.cur_tsc_generation); + + /* + * We track the most recent recorded KHZ, write and time to + * allow the matching interval to be extended at each write. + */ + kvm->arch.last_tsc_nsec = ns; + kvm->arch.last_tsc_write = tsc; + kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz; + + vcpu->arch.last_guest_tsc = tsc; + + /* Keep track of which generation this VCPU has synchronized to */ + vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation; + vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec; + vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write; + + kvm_vcpu_write_tsc_offset(vcpu, offset); + + if (!matched) { + /* + * We split periods of matched TSC writes into generations. + * For each generation, we track the original measured + * nanosecond time, offset, and write, so if TSCs are in + * sync, we can match exact offset, and if not, we can match + * exact software computation in compute_guest_tsc() + * + * These values are tracked in kvm->arch.cur_xxx variables. + */ + kvm->arch.cur_tsc_generation++; + kvm->arch.cur_tsc_nsec = ns; + kvm->arch.cur_tsc_write = tsc; + kvm->arch.cur_tsc_offset = offset; + + spin_lock(&kvm->arch.pvclock_gtod_sync_lock); + kvm->arch.nr_vcpus_matched_tsc = 0; + } else if (!already_matched) { + spin_lock(&kvm->arch.pvclock_gtod_sync_lock); + kvm->arch.nr_vcpus_matched_tsc++; + } + + kvm_track_tsc_matching(vcpu); + spin_unlock(&kvm->arch.pvclock_gtod_sync_lock); +} + static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) { struct kvm *kvm = vcpu->kvm; u64 offset, ns, elapsed; unsigned long flags; - bool matched; - bool already_matched; + bool matched = false; bool synchronizing = false; raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags); @@ -2495,50 +2553,9 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) offset = kvm_compute_l1_tsc_offset(vcpu, data); } matched = true; - already_matched = (vcpu->arch.this_tsc_generation == kvm->arch.cur_tsc_generation); - } else { - /* - * We split periods of matched TSC writes into generations. - * For each generation, we track the original measured - * nanosecond time, offset, and write, so if TSCs are in - * sync, we can match exact offset, and if not, we can match - * exact software computation in compute_guest_tsc() - * - * These values are tracked in kvm->arch.cur_xxx variables. - */ - kvm->arch.cur_tsc_generation++; - kvm->arch.cur_tsc_nsec = ns; - kvm->arch.cur_tsc_write = data; - kvm->arch.cur_tsc_offset = offset; - matched = false; } - /* - * We also track th most recent recorded KHZ, write and time to - * allow the matching interval to be extended at each write. - */ - kvm->arch.last_tsc_nsec = ns; - kvm->arch.last_tsc_write = data; - kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz; - - vcpu->arch.last_guest_tsc = data; - - /* Keep track of which generation this VCPU has synchronized to */ - vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation; - vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec; - vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write; - - kvm_vcpu_write_tsc_offset(vcpu, offset); - - spin_lock_irqsave(&kvm->arch.pvclock_gtod_sync_lock, flags); - if (!matched) { - kvm->arch.nr_vcpus_matched_tsc = 0; - } else if (!already_matched) { - kvm->arch.nr_vcpus_matched_tsc++; - } - - kvm_track_tsc_matching(vcpu); - spin_unlock_irqrestore(&kvm->arch.pvclock_gtod_sync_lock, flags); + __kvm_synchronize_tsc(vcpu, offset, data, ns, matched); raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); } From patchwork Wed Aug 4 08:58:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418123 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E53C3C432BE for ; Wed, 4 Aug 2021 08:58:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CC63E61029 for ; Wed, 4 Aug 2021 08:58:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236822AbhHDI6y (ORCPT ); Wed, 4 Aug 2021 04:58:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6x (ORCPT ); Wed, 4 Aug 2021 04:58:53 -0400 Received: from mail-io1-xd4a.google.com (mail-io1-xd4a.google.com [IPv6:2607:f8b0:4864:20::d4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F3895C0613D5 for ; Wed, 4 Aug 2021 01:58:40 -0700 (PDT) Received: by mail-io1-xd4a.google.com with SMTP id d7-20020a6b6e070000b02904c0978ed194so1062536ioh.10 for ; Wed, 04 Aug 2021 01:58:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=x8LPWtdOqJCGz9ZSpM5JrXHjuEyQMoplDMq1Km+kgH0=; b=Au6D/Rvztr8x+Su+/oHB1zmQdKPKKOPs60i1D7hXkjYp9l6h0j9DWswHbfoi6cMVx/ cjoothQhTFpqD3jSDCQ24VbgRhP1N00BTGfvSVXqc4pdGyfiOUF8th/2oUMCVzTjs/E8 WPDPC+v5GLCMg0rbTM5na3j7fyRd/GR0XorrJHmYMLeYrhtyAlVC+ghXc+An64/+5N5Z fVLCeWG7KQ9TzW6MjKrc2hASzDgjGZcA9GK0/shvksegM3ZLWPdVozZazOshAoEZ9GbX WDlgqr8qPRDdjK/ffvbsn+J+q78H7XPdFth0NkJZaioxy4IovF4YAdBGOXh+JbNq/Bz+ PnLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=x8LPWtdOqJCGz9ZSpM5JrXHjuEyQMoplDMq1Km+kgH0=; b=rRJLoYmhRqPtE5pB2v+11EZ2KeBFJT5vhOg2ooU+VyeqZN1cOXROSP1rfiNL9TFFw0 zlw+HdUu5Zm4RoVfXxl7SZEy0i0tu1kBvRTy75dflbLpBG651Gzcm8FXlAdrf8sllofd vOO1SNvg6LPlFFWSoioM1XCwDHcBhB8OvCdMibouhZqNOdCVHRLhRGA6V289MytzejJn LeaxoNxiiZryvHJyKotDoaBnJ+cB7cbKcGe4hnaq7S8GciT5jVfDxUgYppBt31C1KpcX yjXeaTf+DoOKKHfA1jwCz3rFgqh49uqNDhfMA4ASyNNgwjGY1xfY2DKYpj6++KzTr6WV VZ3Q== X-Gm-Message-State: AOAM530tdaD9qUJneu3yhAeyim1Rt26pCRRU2Nk6b2VNdO2zssu0V3KZ 01g8dk3NpU0+iLin4Vh6tMTZYz8lZfOy8Opk9RM7suuwgBIWkK7G0hdTdsDk/skUZP6vzDD8/iq 2Gio6gQ22vsH6c1yb0j+Ov4gI9wm5ZaqYn+BBM+EzE+wv9257w3g0LkMd9Q== X-Google-Smtp-Source: ABdhPJwJZUENE+FwWb/7dNEy0PuIQl8TXpDew9XDjDz/fQ4geLk3Q3U6VoPSJg0+mNpCuFaUZohuvLgh4W8= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a5e:c803:: with SMTP id y3mr762616iol.107.1628067520327; Wed, 04 Aug 2021 01:58:40 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:03 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-6-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 05/21] KVM: x86: Expose TSC offset controls to userspace From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org To date, VMM-directed TSC synchronization and migration has been a bit messy. KVM has some baked-in heuristics around TSC writes to infer if the VMM is attempting to synchronize. This is problematic, as it depends on host userspace writing to the guest's TSC within 1 second of the last write. A much cleaner approach to configuring the guest's views of the TSC is to simply migrate the TSC offset for every vCPU. Offsets are idempotent, and thus not subject to change depending on when the VMM actually reads/writes values from/to KVM. The VMM can then read the TSC once with KVM_GET_CLOCK to capture a (realtime, host_tsc) pair at the instant when the guest is paused. Cc: David Matlack Cc: Sean Christopherson Signed-off-by: Oliver Upton --- Documentation/virt/kvm/devices/vcpu.rst | 57 +++++++++++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/uapi/asm/kvm.h | 4 + arch/x86/kvm/x86.c | 109 ++++++++++++++++++++++++ 4 files changed, 171 insertions(+) diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst index 2acec3b9ef65..3b399d727c11 100644 --- a/Documentation/virt/kvm/devices/vcpu.rst +++ b/Documentation/virt/kvm/devices/vcpu.rst @@ -161,3 +161,60 @@ Specifies the base address of the stolen time structure for this VCPU. The base address must be 64 byte aligned and exist within a valid guest memory region. See Documentation/virt/kvm/arm/pvtime.rst for more information including the layout of the stolen time structure. + +4. GROUP: KVM_VCPU_TSC_CTRL +=========================== + +:Architectures: x86 + +4.1 ATTRIBUTE: KVM_VCPU_TSC_OFFSET + +:Parameters: 64-bit unsigned TSC offset + +Returns: + + ======= ====================================== + -EFAULT Error reading/writing the provided + parameter address. + -ENXIO Attribute not supported + ======= ====================================== + +Specifies the guest's TSC offset relative to the host's TSC. The guest's +TSC is then derived by the following equation: + + guest_tsc = host_tsc + KVM_VCPU_TSC_OFFSET + +This attribute is useful for the precise migration of a guest's TSC. The +following describes a possible algorithm to use for the migration of a +guest's TSC: + +From the source VMM process: + +1. Invoke the KVM_GET_CLOCK ioctl to record the host TSC (t_0), + kvmclock nanoseconds (k_0), and realtime nanoseconds (r_0). + +2. Read the KVM_VCPU_TSC_OFFSET attribute for every vCPU to record the + guest TSC offset (off_n). + +3. Invoke the KVM_GET_TSC_KHZ ioctl to record the frequency of the + guest's TSC (freq). + +From the destination VMM process: + +4. Invoke the KVM_SET_CLOCK ioctl, providing the kvmclock nanoseconds + (k_0) and realtime nanoseconds (r_0) in their respective fields. + Ensure that the KVM_CLOCK_REALTIME flag is set in the provided + structure. KVM will advance the VM's kvmclock to account for elapsed + time since recording the clock values. + +5. Invoke the KVM_GET_CLOCK ioctl to record the host TSC (t_1) and + kvmclock nanoseconds (k_1). + +6. Adjust the guest TSC offsets for every vCPU to account for (1) time + elapsed since recording state and (2) difference in TSCs between the + source and destination machine: + + new_off_n = t_0 + off_n + (k_1 - k_0) * freq - t_1 + +7. Write the KVM_VCPU_TSC_OFFSET attribute for every vCPU with the + respective value derived in the previous step. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index d6376ca8efce..e9bfc00692fb 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1064,6 +1064,7 @@ struct kvm_arch { u64 last_tsc_nsec; u64 last_tsc_write; u32 last_tsc_khz; + u64 last_tsc_offset; u64 cur_tsc_nsec; u64 cur_tsc_write; u64 cur_tsc_offset; diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index a6c327f8ad9e..0b22e1e84e78 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -503,4 +503,8 @@ struct kvm_pmu_event_filter { #define KVM_PMU_EVENT_ALLOW 0 #define KVM_PMU_EVENT_DENY 1 +/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */ +#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */ +#define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */ + #endif /* _ASM_X86_KVM_H */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 91aea751d621..3fdad71e5a36 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2466,6 +2466,7 @@ static void __kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 offset, u64 tsc, kvm->arch.last_tsc_nsec = ns; kvm->arch.last_tsc_write = tsc; kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz; + kvm->arch.last_tsc_offset = offset; vcpu->arch.last_guest_tsc = tsc; @@ -4924,6 +4925,109 @@ static int kvm_set_guest_paused(struct kvm_vcpu *vcpu) return 0; } +static int kvm_arch_tsc_has_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + int r; + + switch (attr->attr) { + case KVM_VCPU_TSC_OFFSET: + r = 0; + break; + default: + r = -ENXIO; + } + + return r; +} + +static int kvm_arch_tsc_get_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + u64 __user *uaddr = (u64 __user *)attr->addr; + int r; + + switch (attr->attr) { + case KVM_VCPU_TSC_OFFSET: + r = -EFAULT; + if (put_user(vcpu->arch.l1_tsc_offset, uaddr)) + break; + r = 0; + break; + default: + r = -ENXIO; + } + + return r; +} + +static int kvm_arch_tsc_set_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + u64 __user *uaddr = (u64 __user *)attr->addr; + struct kvm *kvm = vcpu->kvm; + int r; + + switch (attr->attr) { + case KVM_VCPU_TSC_OFFSET: { + u64 offset, tsc, ns; + unsigned long flags; + bool matched; + + r = -EFAULT; + if (get_user(offset, uaddr)) + break; + + raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags); + + matched = (vcpu->arch.virtual_tsc_khz && + kvm->arch.last_tsc_khz == vcpu->arch.virtual_tsc_khz && + kvm->arch.last_tsc_offset == offset); + + tsc = kvm_scale_tsc(vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio) + offset; + ns = get_kvmclock_base_ns(); + + __kvm_synchronize_tsc(vcpu, offset, tsc, ns, matched); + raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); + + r = 0; + break; + } + default: + r = -ENXIO; + } + + return r; +} + +static int kvm_vcpu_ioctl_device_attr(struct kvm_vcpu *vcpu, + unsigned int ioctl, + void __user *argp) +{ + struct kvm_device_attr attr; + int r; + + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + + if (attr.group != KVM_VCPU_TSC_CTRL) + return -ENXIO; + + switch (ioctl) { + case KVM_HAS_DEVICE_ATTR: + r = kvm_arch_tsc_has_attr(vcpu, &attr); + break; + case KVM_GET_DEVICE_ATTR: + r = kvm_arch_tsc_get_attr(vcpu, &attr); + break; + case KVM_SET_DEVICE_ATTR: + r = kvm_arch_tsc_set_attr(vcpu, &attr); + break; + } + + return r; +} + static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, struct kvm_enable_cap *cap) { @@ -5378,6 +5482,11 @@ long kvm_arch_vcpu_ioctl(struct file *filp, r = __set_sregs2(vcpu, u.sregs2); break; } + case KVM_HAS_DEVICE_ATTR: + case KVM_GET_DEVICE_ATTR: + case KVM_SET_DEVICE_ATTR: + r = kvm_vcpu_ioctl_device_attr(vcpu, ioctl, argp); + break; default: r = -EINVAL; } From patchwork Wed Aug 4 08:58:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418125 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20198C43216 for ; Wed, 4 Aug 2021 08:58:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0908F60F56 for ; Wed, 4 Aug 2021 08:58:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236839AbhHDI6z (ORCPT ); Wed, 4 Aug 2021 04:58:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235421AbhHDI6y (ORCPT ); Wed, 4 Aug 2021 04:58:54 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 217E9C0613D5 for ; Wed, 4 Aug 2021 01:58:42 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id j9-20020a2581490000b02905897d81c63fso2250482ybm.8 for ; Wed, 04 Aug 2021 01:58:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=QZYUzbcXutG2B1XPKYDDaowrOTkrdRCYpxjQmfgRBqw=; b=fg8ZdJyTO1IzZwQnyFmtQzBLyvzLg3oWs5Mwrvzrq7RU1rdysfWLN2A/CA6201R02a 9x/yYSHRuUETBU088OpH41tdmTezHXghlym7jalL4hNQj9khOjSNah3nmR20olJYlpGM NL9UDv3ftB1FzNYvmaswYPXp0iJ0GOb9T8RcGftr9OzVhNA3piITvnnmbrvRoEKYaUs3 TAbiN9VHBzEih5yBmaD0TSgq4w33jIlobvj6FE10tdMiUbNXovPf3cPu5j0dQjIYAP24 xcRWGMUyhFLsg7YJPN15v+gKZLMR1hpOHVLDuC1OOWN4vglBYkL+5BSD3FbMNsMZGkwn KpMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=QZYUzbcXutG2B1XPKYDDaowrOTkrdRCYpxjQmfgRBqw=; b=JwbuF/CHYBdfggpa75qHYDiE4Wum814xn6q80r8GD8ouva9qoR4/K+Fc8qsD43QJZ/ cxPGzOF61Bl0MBZYr55I1fVufq9EiYW99o8kHXRQtNbyQiibjAIZ7A/iZOuPHdaGPrdp dyWE/vBCJUqiKFdVpzgUI60yn+hvsLmkJUNSJLcUz9aG3uRLXNwbW5rWjFabXsqvn2kk JCji/U+c3HUVbOQz9Zsc0/WZ6ddojJYutQFgS08Kvh5JiVRZEVVGH993bfgs1qcQL/dJ xpeTxI0X99HQ7MrNh4z6/PvtDlA3IYC9Ta3rxp4R2p1267JJ95Hyqpc3DcWpwdEFy1R7 emQA== X-Gm-Message-State: AOAM532l4DTnmkEpjl93NttrhTYiEDYnQSEqdEHHYiz9THO0c0wktNUI 8qf75CaPqpqJ0o3WW/M9pGZUcNdd7p7O1YfZ3PjzsDtponduaaIThRnIbKnLPgOiDOI+BGrvUDR gLP65JxKMGcQsmiNKnSDRLxD1QcIVmqF5ETaa0u5N0BRjkf3ASvlGXP0UVA== X-Google-Smtp-Source: ABdhPJxV6+3gLGbTheDt4LD8pHoTTfHfR6GcLwPPsqBvh7B9FGBWOPkR9xVf9DHE0p02LBy+6d+tyicSFeI= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a25:4283:: with SMTP id p125mr35878914yba.184.1628067521137; Wed, 04 Aug 2021 01:58:41 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:04 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-7-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 06/21] tools: arch: x86: pull in pvclock headers From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Copy over approximately clean versions of the pvclock headers into tools. Reconcile headers/symbols missing in tools that are unneeded. Signed-off-by: Oliver Upton --- tools/arch/x86/include/asm/pvclock-abi.h | 48 +++++++++++ tools/arch/x86/include/asm/pvclock.h | 103 +++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 tools/arch/x86/include/asm/pvclock-abi.h create mode 100644 tools/arch/x86/include/asm/pvclock.h diff --git a/tools/arch/x86/include/asm/pvclock-abi.h b/tools/arch/x86/include/asm/pvclock-abi.h new file mode 100644 index 000000000000..1436226efe3e --- /dev/null +++ b/tools/arch/x86/include/asm/pvclock-abi.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_PVCLOCK_ABI_H +#define _ASM_X86_PVCLOCK_ABI_H +#ifndef __ASSEMBLY__ + +/* + * These structs MUST NOT be changed. + * They are the ABI between hypervisor and guest OS. + * Both Xen and KVM are using this. + * + * pvclock_vcpu_time_info holds the system time and the tsc timestamp + * of the last update. So the guest can use the tsc delta to get a + * more precise system time. There is one per virtual cpu. + * + * pvclock_wall_clock references the point in time when the system + * time was zero (usually boot time), thus the guest calculates the + * current wall clock by adding the system time. + * + * Protocol for the "version" fields is: hypervisor raises it (making + * it uneven) before it starts updating the fields and raises it again + * (making it even) when it is done. Thus the guest can make sure the + * time values it got are consistent by checking the version before + * and after reading them. + */ + +struct pvclock_vcpu_time_info { + u32 version; + u32 pad0; + u64 tsc_timestamp; + u64 system_time; + u32 tsc_to_system_mul; + s8 tsc_shift; + u8 flags; + u8 pad[2]; +} __attribute__((__packed__)); /* 32 bytes */ + +struct pvclock_wall_clock { + u32 version; + u32 sec; + u32 nsec; +} __attribute__((__packed__)); + +#define PVCLOCK_TSC_STABLE_BIT (1 << 0) +#define PVCLOCK_GUEST_STOPPED (1 << 1) +/* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */ +#define PVCLOCK_COUNTS_FROM_ZERO (1 << 2) +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_PVCLOCK_ABI_H */ diff --git a/tools/arch/x86/include/asm/pvclock.h b/tools/arch/x86/include/asm/pvclock.h new file mode 100644 index 000000000000..2628f9a6330b --- /dev/null +++ b/tools/arch/x86/include/asm/pvclock.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_PVCLOCK_H +#define _ASM_X86_PVCLOCK_H + +#include +#include + +/* some helper functions for xen and kvm pv clock sources */ +u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); +u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); +void pvclock_set_flags(u8 flags); +unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); +void pvclock_resume(void); + +void pvclock_touch_watchdogs(void); + +static __always_inline +unsigned pvclock_read_begin(const struct pvclock_vcpu_time_info *src) +{ + unsigned version = src->version & ~1; + /* Make sure that the version is read before the data. */ + rmb(); + return version; +} + +static __always_inline +bool pvclock_read_retry(const struct pvclock_vcpu_time_info *src, + unsigned version) +{ + /* Make sure that the version is re-read after the data. */ + rmb(); + return version != src->version; +} + +/* + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, + * yielding a 64-bit result. + */ +static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) +{ + u64 product; +#ifdef __i386__ + u32 tmp1, tmp2; +#else + unsigned long tmp; +#endif + + if (shift < 0) + delta >>= -shift; + else + delta <<= shift; + +#ifdef __i386__ + __asm__ ( + "mul %5 ; " + "mov %4,%%eax ; " + "mov %%edx,%4 ; " + "mul %5 ; " + "xor %5,%5 ; " + "add %4,%%eax ; " + "adc %5,%%edx ; " + : "=A" (product), "=r" (tmp1), "=r" (tmp2) + : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); +#elif defined(__x86_64__) + __asm__ ( + "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]" + : [lo]"=a"(product), + [hi]"=d"(tmp) + : "0"(delta), + [mul_frac]"rm"((u64)mul_frac)); +#else +#error implement me! +#endif + + return product; +} + +static __always_inline +u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc) +{ + u64 delta = tsc - src->tsc_timestamp; + u64 offset = pvclock_scale_delta(delta, src->tsc_to_system_mul, + src->tsc_shift); + return src->system_time + offset; +} + +struct pvclock_vsyscall_time_info { + struct pvclock_vcpu_time_info pvti; +} __attribute__((__aligned__(64))); + +#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info) + +#ifdef CONFIG_PARAVIRT_CLOCK +void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti); +struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void); +#else +static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void) +{ + return NULL; +} +#endif + +#endif /* _ASM_X86_PVCLOCK_H */ From patchwork Wed Aug 4 08:58:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418127 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-23.5 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D04D9C4320A for ; Wed, 4 Aug 2021 08:58:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B920060F8F for ; Wed, 4 Aug 2021 08:58:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235421AbhHDI64 (ORCPT ); Wed, 4 Aug 2021 04:58:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236833AbhHDI6z (ORCPT ); Wed, 4 Aug 2021 04:58:55 -0400 Received: from mail-il1-x149.google.com (mail-il1-x149.google.com [IPv6:2607:f8b0:4864:20::149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB8ADC0613D5 for ; Wed, 4 Aug 2021 01:58:42 -0700 (PDT) Received: by mail-il1-x149.google.com with SMTP id i4-20020a056e0212c4b029022291c9f509so620153ilm.6 for ; Wed, 04 Aug 2021 01:58:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=fWcniuNXCUCuPv57yCdSEdrKkifvC8A89oeC6WgOzN8=; b=a9oOAkp4mvbQXissCbYue355AXwUJT0HyqVBhuZt9Uq2Oyi8tVlNMo/c/bZSF5LyrW mHB4/6yIVqensNawvm9tyvWFjoT+YkB0Tvb7Mic09FxwsneEGvLKtmQWfbfkfGC0NN00 +WBONgVMZ7jhm2uwJuAkeDE9h/2mo/bjkfi9kt5ci3bceCDwhMnxiujgpDx34DfOPk8z +H6PUQQa+YSiUjG18yfhsQw3IWbzPPu4m4POcWBtJFo9mgA6yxSEgZpi3jhcqfRxVb9y B6z69N+o/U5y7TGF/p0TcAP9yTuhdp69m0eQKJbQ91Ap69SkvekfHzoR6FVEoxXf0+LF Ov8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=fWcniuNXCUCuPv57yCdSEdrKkifvC8A89oeC6WgOzN8=; b=X2PpAL4gvE9VNOKGDS72ZW8YpYqDwyK8LuPIaD/A/zlI/WPfPm/kJRNTrrrl3SpzQY NB8njwHO7yn6GWNi0TkRA+VuMP3+dX50ukiipZalufPAzVX8A0tGge+zA2m93OEiHI5Z QLWcUaBIX7vAfzdtkimb8EgS+1qUdEyxyX2hmUG7LIs6ZpylfnWG7GQtZvYsb0WNF21U Nqxj0YlwTGvHFuMDGt3lWaAF+fBaxtdBxjX7hMoftX0+x7YDC6ubC6L55zslrwbO8P89 nktwsL0e1DQyrksGHIJKBjlVYJXY/R5Z58gNEzMrJ7kVrgTnnRVsUf4oDnlMZCq0pBEs eOOg== X-Gm-Message-State: AOAM530RQHMOeo6BxavNN9BpeYXP8b8pGNTfxaEGIXi7Eu4RFIavbaXT IPnItBj+C6ntv1EwvE1JuSMp58Sak+Tx/trsEmD5JEwDQaGoctRVywyQZ7wltvYckekzgk633Pj wBSRLBuhUm/8Sa2Boh2z6XJJyeJTqhcsdnJqEye6noytSegZXoYC5mv6bxg== X-Google-Smtp-Source: ABdhPJyAyc/dU3nSEvjNvxPG8j4g40KIoOuCzRMMt1RHb+qZXYIlBxONKqT8lMuEOfBkT/Z+tisIzU18bGY= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a5d:9808:: with SMTP id a8mr135685iol.1.1628067522287; Wed, 04 Aug 2021 01:58:42 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:05 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-8-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 07/21] selftests: KVM: Add test for KVM_{GET,SET}_CLOCK From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a selftest for the new KVM clock UAPI that was introduced. Ensure that the KVM clock is consistent between userspace and the guest, and that the difference in realtime will only ever cause the KVM clock to advance forward. Cc: Andrew Jones Signed-off-by: Oliver Upton --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/include/kvm_util.h | 2 + .../selftests/kvm/x86_64/kvm_clock_test.c | 204 ++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/kvm_clock_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 36896d251977..958a809c8de4 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -11,6 +11,7 @@ /x86_64/emulator_error_test /x86_64/get_cpuid_test /x86_64/get_msr_index_features +/x86_64/kvm_clock_test /x86_64/kvm_pv_test /x86_64/hyperv_clock /x86_64/hyperv_cpuid diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index c103873531e0..0f94b18b33ce 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -46,6 +46,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/get_cpuid_test TEST_GEN_PROGS_x86_64 += x86_64/hyperv_clock TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid TEST_GEN_PROGS_x86_64 += x86_64/hyperv_features +TEST_GEN_PROGS_x86_64 += x86_64/kvm_clock_test TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test TEST_GEN_PROGS_x86_64 += x86_64/mmu_role_test diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index 010b59b13917..a8ac5d52e17b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -19,6 +19,8 @@ #define KVM_DEV_PATH "/dev/kvm" #define KVM_MAX_VCPUS 512 +#define NSEC_PER_SEC 1000000000L + /* * Callers of kvm_util only have an incomplete/opaque description of the * structure kvm_util is using to maintain the state of a VM. diff --git a/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c b/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c new file mode 100644 index 000000000000..e0dcc27ae9f1 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/kvm_clock_test.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021, Google LLC. + * + * Tests for adjusting the KVM clock from userspace + */ +#include +#include +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define VCPU_ID 0 + +struct test_case { + uint64_t kvmclock_base; + int64_t realtime_offset; +}; + +static struct test_case test_cases[] = { + { .kvmclock_base = 0 }, + { .kvmclock_base = 180 * NSEC_PER_SEC }, + { .kvmclock_base = 0, .realtime_offset = -180 * NSEC_PER_SEC }, + { .kvmclock_base = 0, .realtime_offset = 180 * NSEC_PER_SEC }, +}; + +#define GUEST_SYNC_CLOCK(__stage, __val) \ + GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0) + +static void guest_main(vm_paddr_t pvti_pa, struct pvclock_vcpu_time_info *pvti) +{ + int i; + + wrmsr(MSR_KVM_SYSTEM_TIME_NEW, pvti_pa | KVM_MSR_ENABLED); + for (i = 0; i < ARRAY_SIZE(test_cases); i++) + GUEST_SYNC_CLOCK(i, __pvclock_read_cycles(pvti, rdtsc())); +} + +#define EXPECTED_FLAGS (KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC) + +static inline void assert_flags(struct kvm_clock_data *data) +{ + TEST_ASSERT((data->flags & EXPECTED_FLAGS) == EXPECTED_FLAGS, + "unexpected clock data flags: %x (want set: %x)", + data->flags, EXPECTED_FLAGS); +} + +static void handle_sync(struct ucall *uc, struct kvm_clock_data *start, + struct kvm_clock_data *end) +{ + uint64_t obs, exp_lo, exp_hi; + + obs = uc->args[2]; + exp_lo = start->clock; + exp_hi = end->clock; + + assert_flags(start); + assert_flags(end); + + TEST_ASSERT(exp_lo <= obs && obs <= exp_hi, + "unexpected kvm-clock value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]", + obs, exp_lo, exp_hi); + + pr_info("kvm-clock value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n", + obs, exp_lo, exp_hi); +} + +static void handle_abort(struct ucall *uc) +{ + TEST_FAIL("%s at %s:%ld", (const char *)uc->args[0], + __FILE__, uc->args[1]); +} + +static void setup_clock(struct kvm_vm *vm, struct test_case *test_case) +{ + struct kvm_clock_data data; + + memset(&data, 0, sizeof(data)); + + data.clock = test_case->kvmclock_base; + if (test_case->realtime_offset) { + struct timespec ts; + int r; + + data.flags |= KVM_CLOCK_REALTIME; + do { + r = clock_gettime(CLOCK_REALTIME, &ts); + if (!r) + break; + } while (errno == EINTR); + + TEST_ASSERT(!r, "clock_gettime() failed: %d\n", r); + + data.realtime = ts.tv_sec * NSEC_PER_SEC; + data.realtime += ts.tv_nsec; + data.realtime += test_case->realtime_offset; + } + + vm_ioctl(vm, KVM_SET_CLOCK, &data); +} + +static void enter_guest(struct kvm_vm *vm) +{ + struct kvm_clock_data start, end; + struct kvm_run *run; + struct ucall uc; + int i, r; + + run = vcpu_state(vm, VCPU_ID); + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + setup_clock(vm, &test_cases[i]); + + vm_ioctl(vm, KVM_GET_CLOCK, &start); + + r = _vcpu_run(vm, VCPU_ID); + vm_ioctl(vm, KVM_GET_CLOCK, &end); + + TEST_ASSERT(!r, "vcpu_run failed: %d\n", r); + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "unexpected exit reason: %u (%s)", + run->exit_reason, exit_reason_str(run->exit_reason)); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_SYNC: + handle_sync(&uc, &start, &end); + break; + case UCALL_ABORT: + handle_abort(&uc); + return; + default: + TEST_ASSERT(0, "unhandled ucall: %ld\n", + get_ucall(vm, VCPU_ID, &uc)); + } + } +} + +#define CLOCKSOURCE_PATH "/sys/devices/system/clocksource/clocksource0/current_clocksource" + +static void check_clocksource(void) +{ + char *clk_name; + struct stat st; + FILE *fp; + + fp = fopen(CLOCKSOURCE_PATH, "r"); + if (!fp) { + pr_info("failed to open clocksource file: %d; assuming TSC.\n", + errno); + return; + } + + if (fstat(fileno(fp), &st)) { + pr_info("failed to stat clocksource file: %d; assuming TSC.\n", + errno); + goto out; + } + + clk_name = malloc(st.st_size); + TEST_ASSERT(clk_name, "failed to allocate buffer to read file\n"); + + if (!fgets(clk_name, st.st_size, fp)) { + pr_info("failed to read clocksource file: %d; assuming TSC.\n", + ferror(fp)); + goto out; + } + + TEST_ASSERT(!strncmp(clk_name, "tsc\n", st.st_size), + "clocksource not supported: %s", clk_name); +out: + fclose(fp); +} + +int main(void) +{ + vm_vaddr_t pvti_gva; + vm_paddr_t pvti_gpa; + struct kvm_vm *vm; + int flags; + + flags = kvm_check_cap(KVM_CAP_ADJUST_CLOCK); + if (!(flags & KVM_CLOCK_REALTIME)) { + print_skip("KVM_CLOCK_REALTIME not supported; flags: %x", + flags); + exit(KSFT_SKIP); + } + + check_clocksource(); + + vm = vm_create_default(VCPU_ID, 0, guest_main); + + pvti_gva = vm_vaddr_alloc(vm, getpagesize(), 0x10000); + pvti_gpa = addr_gva2gpa(vm, pvti_gva); + vcpu_args_set(vm, VCPU_ID, 2, pvti_gpa, pvti_gva); + + enter_guest(vm); + kvm_vm_free(vm); +} From patchwork Wed Aug 4 08:58:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418129 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD92FC432BE for ; Wed, 4 Aug 2021 08:58:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B96CB61037 for ; Wed, 4 Aug 2021 08:58:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236847AbhHDI65 (ORCPT ); Wed, 4 Aug 2021 04:58:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236830AbhHDI64 (ORCPT ); Wed, 4 Aug 2021 04:58:56 -0400 Received: from mail-oi1-x24a.google.com (mail-oi1-x24a.google.com [IPv6:2607:f8b0:4864:20::24a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A81BC0613D5 for ; Wed, 4 Aug 2021 01:58:44 -0700 (PDT) Received: by mail-oi1-x24a.google.com with SMTP id o5-20020a0568080bc5b029025cbda427bbso833837oik.5 for ; Wed, 04 Aug 2021 01:58:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=gCg0AznWgA4f1SrJgUwp//MIUEfrq8bP1cnOz9mraho=; b=MTCyPCTw0RZ+dPZ2ozrA+5wli9Ay+UMDLegw4vajpPfpUxDPSiKLc0KjPDr4t1VbV+ J5VC+2D7LilUe7K9hJUgzZnIgERsJnXnBOOJYtyh6k6G9qjp7rB8PeWklTOaYdZpRZBf Adib//0K6WdMcr9nPQKZ/DWsF8taEaq+gazsww/VYX1ooxIuECdYs3LHF/RsUdd5IJOD XsBqzD2xkkZt2+J8vZhLXIt8kNwajcSPkONGtG2CEIG2seo6FgP/ztuUH/GpEm5NJjZA C8Buw2XEUbP1aCptyDiqWmQAmJ9h3TUzJU2weTZs6VSF8YzfckKutAH1jJXm2v8olilU PR3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=gCg0AznWgA4f1SrJgUwp//MIUEfrq8bP1cnOz9mraho=; b=iuPDeA3hGZgEPlmmQfyAJhuDdh0++vYSU0HVgyRWAXXGWQ/squ9gsLq3XLJs/wWAtm E0qGv1YhVSK1RJhfJGRJvb7svMe+RgiVyTTkqzaJdwjffOfStvCOVxvkvxEq7z3uFLme EnQSdRahUtZ5TYpuYaRSJZOse35BFM4pFyQTwu4wlnHgRSIK2dwn9Y95DOGGPfTadjhj XE29j/T8HJon0f+NjNiVWUp+lNjdWus7BwF+E4xDSvk0O48daDouowSTNtmIt4vRnpyn AvAL7NC62YuTGcYMSO5mkTiGO4x4q23MpW48U/omnJA6iwpzXMLY7ZUcSVpNsH238EQT 1RXQ== X-Gm-Message-State: AOAM532gdh/ZK3VVf2neh7Y9gpHnVTx1Uurpsx/arwMqLofVQGaJNp4O V7LxzeVJe24PB/rOC3WjOksp0L6H/5C+V3wzCqXkgueqBZhxeTrageC1XJNsERlXiTxwMjZYcPY 3zRFCnY5mKzL0z7H5PKb61gTsLB0VMD0cmTwjYDldfTAYZ40ZUNHcqATzrA== X-Google-Smtp-Source: ABdhPJyrF6Z/oAvVMCwq6Zwnl1O8bPPs3vKcjVomi62Qv2JKaBWWKXDpL2ITIDF27NgJQLbzg5F4wv4SoZ4= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6808:68d:: with SMTP id k13mr17591632oig.83.1628067523355; Wed, 04 Aug 2021 01:58:43 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:06 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-9-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 08/21] selftests: KVM: Fix kvm device helper ioctl assertions From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The KVM_CREATE_DEVICE and KVM_{GET,SET}_DEVICE_ATTR ioctls are defined to return a value of zero on success. As such, tighten the assertions in the helper functions to only pass if the return code is zero. Suggested-by: Andrew Jones Reviewed-by: Andrew Jones Signed-off-by: Oliver Upton --- tools/testing/selftests/kvm/lib/kvm_util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 10a8ed691c66..0ffc2d39c80d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1984,7 +1984,7 @@ int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr) { int ret = _kvm_device_check_attr(dev_fd, group, attr); - TEST_ASSERT(ret >= 0, "KVM_HAS_DEVICE_ATTR failed, rc: %i errno: %i", ret, errno); + TEST_ASSERT(!ret, "KVM_HAS_DEVICE_ATTR failed, rc: %i errno: %i", ret, errno); return ret; } @@ -2008,7 +2008,7 @@ int kvm_create_device(struct kvm_vm *vm, uint64_t type, bool test) ret = _kvm_create_device(vm, type, test, &fd); if (!test) { - TEST_ASSERT(ret >= 0, + TEST_ASSERT(!ret, "KVM_CREATE_DEVICE IOCTL failed, rc: %i errno: %i", ret, errno); return fd; } @@ -2036,7 +2036,7 @@ int kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, { int ret = _kvm_device_access(dev_fd, group, attr, val, write); - TEST_ASSERT(ret >= 0, "KVM_SET|GET_DEVICE_ATTR IOCTL failed, rc: %i errno: %i", ret, errno); + TEST_ASSERT(!ret, "KVM_SET|GET_DEVICE_ATTR IOCTL failed, rc: %i errno: %i", ret, errno); return ret; } From patchwork Wed Aug 4 08:58:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418131 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2B31C43214 for ; Wed, 4 Aug 2021 08:58:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E11A060FC4 for ; Wed, 4 Aug 2021 08:58:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236846AbhHDI66 (ORCPT ); Wed, 4 Aug 2021 04:58:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236830AbhHDI65 (ORCPT ); Wed, 4 Aug 2021 04:58:57 -0400 Received: from mail-il1-x14a.google.com (mail-il1-x14a.google.com [IPv6:2607:f8b0:4864:20::14a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DB5AC0613D5 for ; Wed, 4 Aug 2021 01:58:45 -0700 (PDT) Received: by mail-il1-x14a.google.com with SMTP id l4-20020a9270040000b02901bb78581beaso612410ilc.12 for ; Wed, 04 Aug 2021 01:58:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=2gjqXaybcfhGsEx7zzFhczi+7waNRcsT2EekTwdua3g=; b=mV3bavEsQJeFXoUN6afZIex4P+pbiEQskKr9ssIEpwxYxDVbr44+z5lsJsI++Z/9Eq KeBYAqy8laLfZxljKzYQhBLHzT6bqtxYdHktSuVRjDa5Gtqs4iAqWXpfdIpAy1KXSun4 gqNKIV1hLNTLPBmE9EtHKMmmZHP9aWDOkxcA/VE7YzVuVw3idutZtbZD6+c0QLCQN1H/ WTZV0519PCAPuQI5oN6Yhk1r2JrU/cSC6/FfKZYANGe19iGPgRK8igSbV3Do7eoWVteQ gweezT4+LUU7GWjD02ej83+efT++D1RXYMUsW8G2eiB3aMOuJUHJ8KDDFJIHK56sKCZA ShCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=2gjqXaybcfhGsEx7zzFhczi+7waNRcsT2EekTwdua3g=; b=nhSlJ3ISTwMjD0edR1K3iW14VLBmZEmxHQOLL3H1H6RajUlm8zIKw+qdYx1eQY0Nvt fW+eM5UuRQN9AHz0QrOUVp9A1vTh01pzmgHq7O4lseWYERzO57e/7kGicgdiyMZoBFHi MCFulTIV8tvA8dLyiQcVyb9RMJk0G227JLbMnDYAlCcNBF+dT3UYqtGLnnk3XSJY6VfT qKLPfspBDOg82GvCYFQQ02/JCijnGwQBS9TvqjixiTmtSQZwuKtjuuPb37ywM5oYjAxN nLLLEPB7ruq/YbpmN1LaW94GVwQcVDPwhIUfveEnQ2iOfPaPjvduVytC9fYFPPZwfaNz XoHQ== X-Gm-Message-State: AOAM53343BgN7mhpNjueM9Jul0XtuIypsezYWqm4U4SFs8hIsJgdmvg2 s7cKP7w1P/f+Kbbq2n+wSZJ1273DoZsAAEwG+FovraxxGWvIMzEV9gPbsTAIwSbjY+jJ5KED928 yh7BfTy8PrKMVOjCNL07zObsuQSOxWLgbnsKioaW2KNpcQEhjYF2qi8r2BA== X-Google-Smtp-Source: ABdhPJycrlSIwAp+3SfcqVpiRRWeZMq52Xk/yfwClIcOtkMb1s3+t/Zxk/Hhj0Y7XyAdi6gYQ6pBF51nN/o= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a02:9385:: with SMTP id z5mr1643218jah.95.1628067524697; Wed, 04 Aug 2021 01:58:44 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:07 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-10-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 09/21] selftests: KVM: Add helpers for vCPU device attributes From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org vCPU file descriptors are abstracted away from test code in KVM selftests, meaning that tests cannot directly access a vCPU's device attributes. Add helpers that tests can use to get at vCPU device attributes. Reviewed-by: Andrew Jones Signed-off-by: Oliver Upton --- .../testing/selftests/kvm/include/kvm_util.h | 9 +++++ tools/testing/selftests/kvm/lib/kvm_util.c | 38 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index a8ac5d52e17b..1b3ef5757819 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -240,6 +240,15 @@ int _kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, int kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, void *val, bool write); +int _vcpu_has_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr); +int vcpu_has_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr); +int _vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr, void *val, bool write); +int vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr, void *val, bool write); + const char *exit_reason_str(unsigned int exit_reason); void virt_pgd_alloc(struct kvm_vm *vm); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 0ffc2d39c80d..0fe66ca6139a 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -2040,6 +2040,44 @@ int kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, return ret; } +int _vcpu_has_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr) +{ + struct vcpu *vcpu = vcpu_find(vm, vcpuid); + + TEST_ASSERT(vcpu, "nonexistent vcpu id: %d", vcpuid); + + return _kvm_device_check_attr(vcpu->fd, group, attr); +} + +int vcpu_has_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr) +{ + int ret = _vcpu_has_device_attr(vm, vcpuid, group, attr); + + TEST_ASSERT(!ret, "KVM_HAS_DEVICE_ATTR IOCTL failed, rc: %i errno: %i", ret, errno); + return ret; +} + +int _vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr, void *val, bool write) +{ + struct vcpu *vcpu = vcpu_find(vm, vcpuid); + + TEST_ASSERT(vcpu, "nonexistent vcpu id: %d", vcpuid); + + return _kvm_device_access(vcpu->fd, group, attr, val, write); +} + +int vcpu_access_device_attr(struct kvm_vm *vm, uint32_t vcpuid, uint32_t group, + uint64_t attr, void *val, bool write) +{ + int ret = _vcpu_access_device_attr(vm, vcpuid, group, attr, val, write); + + TEST_ASSERT(!ret, "KVM_SET|GET_DEVICE_ATTR IOCTL failed, rc: %i errno: %i", ret, errno); + return ret; +} + /* * VM Dump * From patchwork Wed Aug 4 08:58:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418133 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-23.5 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5E0AC432BE for ; Wed, 4 Aug 2021 08:58:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9392660F8F for ; Wed, 4 Aug 2021 08:58:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236857AbhHDI67 (ORCPT ); Wed, 4 Aug 2021 04:58:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35092 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236849AbhHDI66 (ORCPT ); Wed, 4 Aug 2021 04:58:58 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B03CC061798 for ; Wed, 4 Aug 2021 01:58:46 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id f3-20020a25cf030000b029055a2303fc2dso2245445ybg.11 for ; Wed, 04 Aug 2021 01:58:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=r41+4YYQSiRGA4d6k0mbGoII8JeQ9p3vNbErRM95pUY=; b=i1JP0767Kq2eMPERgaGvHbggJeZJvodxcSvZQy51OakaKa1Cbqy9xm+/eZdOHxqRmC fFh58lUBru2qfvCl38Gfb2VU/pDLhL4ITdf3Chejofn87Q6F7gqmswLQe0W3Vt2hSMrW StDqS5nb+AnvztxtI4rLhPA74xkiiidKtOVGH0ktlG8aZR1A1D+6MTGzGX7hQBqntekf kjPuEi+qTGrrP1iuuWD1IiSGwXiXiasHuZm5SuWHvrSnWVvB3PXsT5RFMcSUlvOuDllF U80KyR1DLEKtQ+pIyHVzZx/Fo3vjH8n1ZPMl4hKmqntonTmhWFeKx1hW1HoxYaHAQ3Fx 4n8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=r41+4YYQSiRGA4d6k0mbGoII8JeQ9p3vNbErRM95pUY=; b=LDTJhf4bi30G5IIDv4+oMZjLI5meJWG5HrrpHXODOTnnjLDsmm9XMSRgtGh7nDGcKh kwhuLgHEcg8cs0VPQrf0MNapgXOUjZUzpjvlkfhLKhh1lXYutvgFRVdSGb3lKjnclAeq 344leI+k/ZsFxoeeA1tpZ6QMt1qOfhbRF4mLjZ7UJItLCtsONg44ho8L5mtmPJY6hSsY OnFbSXRUpWMHCCI1dbmyEaWw4G7j+wgFA7RRNgcaTEDWEWiyEtS4u5UhVtFYXCqV/n1Z u3X8nZ9RrHPk0BtzuqgahM9Fz3oSdOmaVxTPVM8rH3OVUKR2m5Edh+htz4q5OtYGCu+e AqzA== X-Gm-Message-State: AOAM5311FBGAlf56zPYOIBVETqGWUnfhE62RfuYI4MsYMO58y2fJ3RLi 9tBTf450G7ooYF/25RPLy6f6N4mTpkYJSBAfVgWW6lFqdeugAWdOTPzdBW1OiJGtBqlOEmGAhHu nrTGmKwKfBF9OflJAPsmyKW4GLZNv62+pUY2b0IiEQHZs5CXwbpALglLX7Q== X-Google-Smtp-Source: ABdhPJwYShJd9P6lwbF9fYm94Q4Zq6gEEsSqgevPCyNL1eua0sBPsWceQGemLO1QF+7+t0wmw+wsImgjHFE= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6902:114c:: with SMTP id p12mr35133135ybu.282.1628067525755; Wed, 04 Aug 2021 01:58:45 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:08 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-11-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 10/21] selftests: KVM: Introduce system counter offset test From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce a KVM selftest to verify that userspace manipulation of the TSC (via the new vCPU attribute) results in the correct behavior within the guest. Reviewed-by: Andrew Jones Signed-off-by: Oliver Upton --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../kvm/system_counter_offset_test.c | 132 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tools/testing/selftests/kvm/system_counter_offset_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 958a809c8de4..3d2585f0bffc 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -52,3 +52,4 @@ /set_memory_region_test /steal_time /kvm_binary_stats_test +/system_counter_offset_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 0f94b18b33ce..9f7060c02668 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -85,6 +85,7 @@ TEST_GEN_PROGS_x86_64 += memslot_perf_test TEST_GEN_PROGS_x86_64 += set_memory_region_test TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test +TEST_GEN_PROGS_x86_64 += system_counter_offset_test TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list diff --git a/tools/testing/selftests/kvm/system_counter_offset_test.c b/tools/testing/selftests/kvm/system_counter_offset_test.c new file mode 100644 index 000000000000..b337bbbfa41f --- /dev/null +++ b/tools/testing/selftests/kvm/system_counter_offset_test.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021, Google LLC. + * + * Tests for adjusting the system counter from userspace + */ +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define VCPU_ID 0 + +#ifdef __x86_64__ + +struct test_case { + uint64_t tsc_offset; +}; + +static struct test_case test_cases[] = { + { 0 }, + { 180 * NSEC_PER_SEC }, + { -180 * NSEC_PER_SEC }, +}; + +static void check_preconditions(struct kvm_vm *vm) +{ + if (!_vcpu_has_device_attr(vm, VCPU_ID, KVM_VCPU_TSC_CTRL, KVM_VCPU_TSC_OFFSET)) + return; + + print_skip("KVM_VCPU_TSC_OFFSET not supported; skipping test"); + exit(KSFT_SKIP); +} + +static void setup_system_counter(struct kvm_vm *vm, struct test_case *test) +{ + vcpu_access_device_attr(vm, VCPU_ID, KVM_VCPU_TSC_CTRL, + KVM_VCPU_TSC_OFFSET, &test->tsc_offset, true); +} + +static uint64_t guest_read_system_counter(struct test_case *test) +{ + return rdtsc(); +} + +static uint64_t host_read_guest_system_counter(struct test_case *test) +{ + return rdtsc() + test->tsc_offset; +} + +#else /* __x86_64__ */ + +#error test not implemented for this architecture! + +#endif + +#define GUEST_SYNC_CLOCK(__stage, __val) \ + GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0) + +static void guest_main(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct test_case *test = &test_cases[i]; + + GUEST_SYNC_CLOCK(i, guest_read_system_counter(test)); + } +} + +static void handle_sync(struct ucall *uc, uint64_t start, uint64_t end) +{ + uint64_t obs = uc->args[2]; + + TEST_ASSERT(start <= obs && obs <= end, + "unexpected system counter value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]", + obs, start, end); + + pr_info("system counter value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n", + obs, start, end); +} + +static void handle_abort(struct ucall *uc) +{ + TEST_FAIL("%s at %s:%ld", (const char *)uc->args[0], + __FILE__, uc->args[1]); +} + +static void enter_guest(struct kvm_vm *vm) +{ + uint64_t start, end; + struct ucall uc; + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct test_case *test = &test_cases[i]; + + setup_system_counter(vm, test); + start = host_read_guest_system_counter(test); + vcpu_run(vm, VCPU_ID); + end = host_read_guest_system_counter(test); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_SYNC: + handle_sync(&uc, start, end); + break; + case UCALL_ABORT: + handle_abort(&uc); + return; + default: + TEST_ASSERT(0, "unhandled ucall %ld\n", + get_ucall(vm, VCPU_ID, &uc)); + } + } +} + +int main(void) +{ + struct kvm_vm *vm; + + vm = vm_create_default(VCPU_ID, 0, guest_main); + check_preconditions(vm); + ucall_init(vm, NULL); + + enter_guest(vm); + kvm_vm_free(vm); +} From patchwork Wed Aug 4 08:58:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418135 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 820B9C4320E for ; Wed, 4 Aug 2021 08:58:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6802960EE9 for ; Wed, 4 Aug 2021 08:58:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236842AbhHDI7A (ORCPT ); Wed, 4 Aug 2021 04:59:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236858AbhHDI67 (ORCPT ); Wed, 4 Aug 2021 04:58:59 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA1F9C06179B for ; Wed, 4 Aug 2021 01:58:47 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id n192-20020a25dac90000b029054c59edf217so2276143ybf.3 for ; Wed, 04 Aug 2021 01:58:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=35TVCGaSXP1YX+xl0ynmypPjFUwRXJIFcUTUP7y3OEA=; b=uZnF95SUd8tPNPh9UDFmW/BkibQwuIqjWxF/hBpRgMBadermRtPRVOXDB9dmgoECSE FKyGfmtyrLDrsggccC+Bh3D5G2gELbtHa3uN0XfY5JKG0ECY2NshKN8FbWDsmNi36LEb ctSbdLL+8gkNDC+TlCJ0gt0RNoAPIKSkADIlXB6qQ9GqhxXiuP9bYTOxBYCK/0CJbLyX OMo5Qd7rEVm7l+Vl0r9z9VADsMHVwgRinpxvMjgoANM3sIcdXewmA5o0ijE8KaMaarny i6gAvU3WwVGrOeGLvkW/NqGz11SdqskIEqbf4Vm2r99E0OmmNmyy0TLewqXP11d4sUzL O8HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=35TVCGaSXP1YX+xl0ynmypPjFUwRXJIFcUTUP7y3OEA=; b=kb34r4tD2heO0dCyyesEt6tuiP+yHQyY/1tUhqZpukVCxXkrNk5RTWe26UH6TVghVF pwC5dczB4ClDsQYU5aEfhm9na76zhWeTmGIV7w4QBsbsS+j9HIaUUdJsLyJYnc8lK0Sa dHIwcrjgpETmqEoXnrPChE2R/UI2kR+co8BAvgd5WjF0KR8uy+p8PXndt6HTj8qniUNj QMlARF3KKKHytQ2QRJxvFMjtegFemle4ad/j9jL54niujk/zpdD9522VPcHdIslHSlx1 QgMMaPfb25qlg1AfuF5je4w6PFKcEtgo+/z7w4rGAoasq977mt2s7IqoaamMCxcDvwLr ZneA== X-Gm-Message-State: AOAM532T+NNFqn4F0za9X4F7CEW3TnxNP+SChTUgE+VMQy9fE34GwmmQ Cu2BEXKKhDo9E/QxPT0jezOAYIO6KwNn66k0WKebn66siRaQ4EyYk3r4/TqPGbCKPGWK4gAHrs8 eCQjMO3awXECZlractoT4b4bESgqpirrGTck5Sq+x9AWm2PN21UGV68UgXw== X-Google-Smtp-Source: ABdhPJwQw2VG+2wPW9YYVkLKNHJyZLMCee16q7ggjAFKp03Ugn+6tAxy0sKWEOCLAMhlJGHciviyBhrNI/s= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a25:8010:: with SMTP id m16mr34219421ybk.210.1628067526796; Wed, 04 Aug 2021 01:58:46 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:09 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-12-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 11/21] KVM: arm64: Refactor update_vtimer_cntvoff() From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Make the implementation of update_vtimer_cntvoff() generic w.r.t. guest timer context and spin off into a new helper method for later use. Require callers of this new helper method to grab the kvm lock beforehand. No functional change intended. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- arch/arm64/kvm/arch_timer.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 3df67c127489..c0101db75ad4 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -747,22 +747,32 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) return 0; } -/* Make the updates of cntvoff for all vtimer contexts atomic */ -static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) +/* Make offset updates for all timer contexts atomic */ +static void update_timer_offset(struct kvm_vcpu *vcpu, + enum kvm_arch_timers timer, u64 offset) { int i; struct kvm *kvm = vcpu->kvm; struct kvm_vcpu *tmp; - mutex_lock(&kvm->lock); + lockdep_assert_held(&kvm->lock); + kvm_for_each_vcpu(i, tmp, kvm) - timer_set_offset(vcpu_vtimer(tmp), cntvoff); + timer_set_offset(vcpu_get_timer(tmp, timer), offset); /* * When called from the vcpu create path, the CPU being created is not * included in the loop above, so we just set it here as well. */ - timer_set_offset(vcpu_vtimer(vcpu), cntvoff); + timer_set_offset(vcpu_get_timer(vcpu, timer), offset); +} + +static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) +{ + struct kvm *kvm = vcpu->kvm; + + mutex_lock(&kvm->lock); + update_timer_offset(vcpu, TIMER_VTIMER, cntvoff); mutex_unlock(&kvm->lock); } From patchwork Wed Aug 4 08:58:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418137 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 843FDC43214 for ; Wed, 4 Aug 2021 08:58:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DB716105A for ; Wed, 4 Aug 2021 08:58:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236845AbhHDI7B (ORCPT ); Wed, 4 Aug 2021 04:59:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236853AbhHDI7A (ORCPT ); Wed, 4 Aug 2021 04:59:00 -0400 Received: from mail-il1-x14a.google.com (mail-il1-x14a.google.com [IPv6:2607:f8b0:4864:20::14a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A56B2C0613D5 for ; Wed, 4 Aug 2021 01:58:48 -0700 (PDT) Received: by mail-il1-x14a.google.com with SMTP id o6-20020a056e020926b0290221b4e37e75so599683ilt.21 for ; Wed, 04 Aug 2021 01:58:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=83fDaIfLsY16yic2+Bpl9lC9hOGkPIV4LchssH1j3LE=; b=SN6GL4hBv6p6nMD4A6e58ghkZoNJfYaNi1MH9O1SIy7AoxXS7cRW68enEg2zIivQkk aZholzalc9xdnfdFzpu9eczDYMKU3+21wWy+fHFgrhF1LmBnspbi1VbEK21vIeTc6TgF rxlaa1A0gISSGbu1UB7PaIEPBWtI6gYPJAV/mOAXQctzT1NMqQZJYYnplqQFgzPN9OjD YtOYVGsAkqQIxCqhX5FD0AOTTtVv8WbFRE/CHjmppQjFKKelImAn2YGU+uu7XY+qyKZr CbnHCJveaEuBZkRFO75LP0K3L/M8CD56y8I6K0CXzIBrVp7Y0gEcqjJiNLCF63KqUPgI uDFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=83fDaIfLsY16yic2+Bpl9lC9hOGkPIV4LchssH1j3LE=; b=IVFVg4Wsxx8RMW2gG40UEaDR0Wn7e9xjBtzIVgPydNMThg0PgLiTCKi5bEOn14yop8 NH0Qb0lkbCnfHDwtpG+38+3qMZ+YPZRXSaxgTMrRPKXjwXnFWV3f8RjtVKhpJ0ZCfXIj Ga57mpsd2rZdhpTGMvtMKjEHcpghJdGatFPpEcCiWxHJ4r/a+uL/bVE64v0oBPftDQ/V vGkl0PLDPsjERVkmCIwFM2ofsNFgq3/BT8AkFAGojLW6XaUQHY54rbxBZhU1RE7sGZ0+ 3FLl7onGwM2ZOLSWELekx9p1KQhqoQ5509zevMAHJ5SPfkIXLHPW8Mh5V3mSYifnNm87 TBNQ== X-Gm-Message-State: AOAM530yPZKQThF/KSjMryUi5VQ4MOt75q8eaDRHFOwt/N95hL/XoRST rG8Qdz4LaXgvMNC1YAkqhjeR0ymo3Tu+l9m97vJZBULfRQtMZdghRWYjzpVY1yaM1yKI7vUeXbt AViC3Xg5Cl6TM12AgGli+PYS/FefH0aoO+819rkEynZqN5UWzzrII6eiVSA== X-Google-Smtp-Source: ABdhPJzi9q8UGwJAYqkti8laANuUPc3nn5R3eDyiiZDnOVn9vGB1o/QfvD8/gVEEbONDuMag3MzbiMyJaWQ= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a92:5205:: with SMTP id g5mr634503ilb.22.1628067527974; Wed, 04 Aug 2021 01:58:47 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:10 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-13-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 12/21] KVM: arm64: Separate guest/host counter offset values From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org In some instances, a VMM may want to update the guest's counter-timer offset in a transparent manner, meaning that changes to the hardware value do not affect the synthetic register presented to the guest or the VMM through said guest's architectural state. Lay the groundwork to separate guest offset register writes from the hardware values utilized by KVM. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- arch/arm64/kvm/arch_timer.c | 48 ++++++++++++++++++++++++++++++++---- include/kvm/arm_arch_timer.h | 3 +++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index c0101db75ad4..4c2b763a8849 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -87,6 +87,18 @@ static u64 timer_get_offset(struct arch_timer_context *ctxt) struct kvm_vcpu *vcpu = ctxt->vcpu; switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + return ctxt->host_offset; + default: + return 0; + } +} + +static u64 timer_get_guest_offset(struct arch_timer_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch (arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); default: @@ -132,13 +144,31 @@ static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset; + ctxt->host_offset = offset; break; default: WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt)); } } +static void timer_set_guest_offset(struct arch_timer_context *ctxt, u64 offset) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch (arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: { + u64 host_offset = timer_get_offset(ctxt); + + host_offset += offset - __vcpu_sys_reg(vcpu, CNTVOFF_EL2); + __vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset; + timer_set_offset(ctxt, host_offset); + break; + } + default: + WARN_ONCE(offset, "timer %ld\n", arch_timer_ctx_index(ctxt)); + } +} + u64 kvm_phys_timer_read(void) { return timecounter->cc->read(timecounter->cc); @@ -749,7 +779,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) /* Make offset updates for all timer contexts atomic */ static void update_timer_offset(struct kvm_vcpu *vcpu, - enum kvm_arch_timers timer, u64 offset) + enum kvm_arch_timers timer, u64 offset, + bool guest_visible) { int i; struct kvm *kvm = vcpu->kvm; @@ -758,13 +789,20 @@ static void update_timer_offset(struct kvm_vcpu *vcpu, lockdep_assert_held(&kvm->lock); kvm_for_each_vcpu(i, tmp, kvm) - timer_set_offset(vcpu_get_timer(tmp, timer), offset); + if (guest_visible) + timer_set_guest_offset(vcpu_get_timer(tmp, timer), + offset); + else + timer_set_offset(vcpu_get_timer(tmp, timer), offset); /* * When called from the vcpu create path, the CPU being created is not * included in the loop above, so we just set it here as well. */ - timer_set_offset(vcpu_get_timer(vcpu, timer), offset); + if (guest_visible) + timer_set_guest_offset(vcpu_get_timer(vcpu, timer), offset); + else + timer_set_offset(vcpu_get_timer(vcpu, timer), offset); } static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) @@ -772,7 +810,7 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) struct kvm *kvm = vcpu->kvm; mutex_lock(&kvm->lock); - update_timer_offset(vcpu, TIMER_VTIMER, cntvoff); + update_timer_offset(vcpu, TIMER_VTIMER, cntvoff, true); mutex_unlock(&kvm->lock); } diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 51c19381108c..9d65d4a29f81 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -42,6 +42,9 @@ struct arch_timer_context { /* Duplicated state from arch_timer.c for convenience */ u32 host_timer_irq; u32 host_timer_irq_flags; + + /* offset relative to the host's physical counter-timer */ + u64 host_offset; }; struct timer_map { From patchwork Wed Aug 4 08:58:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10CC2C4338F for ; Wed, 4 Aug 2021 08:58:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E762061037 for ; Wed, 4 Aug 2021 08:58:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236854AbhHDI7E (ORCPT ); Wed, 4 Aug 2021 04:59:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35130 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236862AbhHDI7C (ORCPT ); Wed, 4 Aug 2021 04:59:02 -0400 Received: from mail-il1-x14a.google.com (mail-il1-x14a.google.com [IPv6:2607:f8b0:4864:20::14a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B76DFC06179A for ; Wed, 4 Aug 2021 01:58:49 -0700 (PDT) Received: by mail-il1-x14a.google.com with SMTP id d6-20020a056e020506b0290208fe58bd16so643546ils.0 for ; Wed, 04 Aug 2021 01:58:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=pHbBznoto/w1DGPJijTV3nfkHaGebmmnj5HwOTBirkc=; b=dn/0nPYXirFwFfUZ2GEAi/qhuxAMc3UdhDO5zmOyzs4xgPPu1Issk8EocASn5/fyv4 MQAn8vRHgozFqMtyCgZVR6SDS4qKCek2Jf+x2jEEDw5+sz044Vt95ZHgm1fwiYxlm8YX ukQuG2II6iGVwSqrZYFdafAwQC+k5t3CTrkXoJIYdnhEJg5alr2F+tA9OPsKKVDSVi3Y BHefOjNKnYGVSyVxjK2UOSfnx1q9BUaOobpoFWPlmrKVCt998wzyV0/IZhMWS0ApXxWH /hZirW/KtZLzZIrUTN+53iSMqDwzzqQ+cCjWotK5YAmKlkmNPQffOWK+hwL4ocJOa0/s a85Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=pHbBznoto/w1DGPJijTV3nfkHaGebmmnj5HwOTBirkc=; b=WY6dV4xCtXzhIAExPvGjqYAlNxu8POBmYc3LV/2iNKZmFhlsbo87HG9GFPydw/lK8G XxrwxSSpBah5ZM3zGhvzDm8wSeHuQIRSPn0u+6uh2+Lc0Shro2mvi3mQI0VEruLunlRc JkI/mf7ktnOlj2iH6A6yZJFDBDXBzq5pyFAVG2a0trKvT4Ad4wPPCATh9E8X+01/qwzU Wy7WX2WUAgxxJ3A/GhhaBLCn/q8jkD/cELudm/i+ZubYgQ5L6V3MWYaS4nQCuvBOuEnA DpgjETiwGKpcOjNAcHCX5xZZYVUN4Z5l8Eg8LfVPUKsp55ySTLKxY9083fh01CPG7BdG u2cg== X-Gm-Message-State: AOAM53364DLGPxzZpO03zxz8jMT3uKiw4pyMcsQp2v6F77eBOGb4lxkY 9wSyodCTJQKAGwe3xPOYu/WZB53NQkJs820fZdm/3kMza2tkN+IZK8sgSGMXVEOaFunfir1nuXh 3J+lkIbIdLHuOHp1sjAWW3n9daS5QRENlnaPEic196Nlvq/+oRas2rLNojg== X-Google-Smtp-Source: ABdhPJx430Og/gl8Ea4doYmCM5gKCd5oDpwqPEalh4SowVARGCh1NYO/9OTpOR3+C6ZHxiOd8eCjQClzb+4= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6e02:54c:: with SMTP id i12mr111057ils.103.1628067529077; Wed, 04 Aug 2021 01:58:49 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:11 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-14-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 13/21] KVM: arm64: Allow userspace to configure a vCPU's virtual offset From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Allow userspace to access the guest's virtual counter-timer offset through the ONE_REG interface. The value read or written is defined to be an offset from the guest's physical counter-timer. Add some documentation to clarify how a VMM should use this and the existing CNTVCT_EL0. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- Documentation/virt/kvm/api.rst | 10 ++++++++++ arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/arch_timer.c | 11 +++++++++++ arch/arm64/kvm/guest.c | 6 +++++- include/kvm/arm_arch_timer.h | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 8d4a3471ad9e..28a65dc89985 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -2487,6 +2487,16 @@ arm64 system registers have the following id bit patterns:: derived from the register encoding for CNTV_CVAL_EL0. As this is API, it must remain this way. +.. warning:: + + The value of KVM_REG_ARM_TIMER_OFFSET is defined as an offset from + the guest's view of the physical counter-timer. + + Userspace should use either KVM_REG_ARM_TIMER_OFFSET or + KVM_REG_ARM_TIMER_CVAL to pause and resume a guest's virtual + counter-timer. Mixed use of these registers could result in an + unpredictable guest counter value. + arm64 firmware pseudo-registers have the following bit pattern:: 0x6030 0000 0014 diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index b3edde68bc3e..949a31bc10f0 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -255,6 +255,7 @@ struct kvm_arm_copy_mte_tags { #define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1) #define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2) #define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2) +#define KVM_REG_ARM_TIMER_OFFSET ARM64_SYS_REG(3, 4, 14, 0, 3) /* KVM-as-firmware specific pseudo-registers */ #define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 4c2b763a8849..a8815b09da3e 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -868,6 +868,10 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) timer = vcpu_vtimer(vcpu); kvm_arm_timer_write(vcpu, timer, TIMER_REG_CVAL, value); break; + case KVM_REG_ARM_TIMER_OFFSET: + timer = vcpu_vtimer(vcpu); + update_vtimer_cntvoff(vcpu, value); + break; case KVM_REG_ARM_PTIMER_CTL: timer = vcpu_ptimer(vcpu); kvm_arm_timer_write(vcpu, timer, TIMER_REG_CTL, value); @@ -912,6 +916,9 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) case KVM_REG_ARM_TIMER_CVAL: return kvm_arm_timer_read(vcpu, vcpu_vtimer(vcpu), TIMER_REG_CVAL); + case KVM_REG_ARM_TIMER_OFFSET: + return kvm_arm_timer_read(vcpu, + vcpu_vtimer(vcpu), TIMER_REG_OFFSET); case KVM_REG_ARM_PTIMER_CTL: return kvm_arm_timer_read(vcpu, vcpu_ptimer(vcpu), TIMER_REG_CTL); @@ -949,6 +956,10 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, val = kvm_phys_timer_read() - timer_get_offset(timer); break; + case TIMER_REG_OFFSET: + val = timer_get_offset(timer); + break; + default: BUG(); } diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 1dfb83578277..17fc06e2b422 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -591,7 +591,7 @@ static unsigned long num_core_regs(const struct kvm_vcpu *vcpu) * ARM64 versions of the TIMER registers, always available on arm64 */ -#define NUM_TIMER_REGS 3 +#define NUM_TIMER_REGS 4 static bool is_timer_reg(u64 index) { @@ -599,6 +599,7 @@ static bool is_timer_reg(u64 index) case KVM_REG_ARM_TIMER_CTL: case KVM_REG_ARM_TIMER_CNT: case KVM_REG_ARM_TIMER_CVAL: + case KVM_REG_ARM_TIMER_OFFSET: return true; } return false; @@ -614,6 +615,9 @@ static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) uindices++; if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices)) return -EFAULT; + uindices++; + if (put_user(KVM_REG_ARM_TIMER_OFFSET, uindices)) + return -EFAULT; return 0; } diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 9d65d4a29f81..615f9314f6a5 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -21,6 +21,7 @@ enum kvm_arch_timer_regs { TIMER_REG_CVAL, TIMER_REG_TVAL, TIMER_REG_CTL, + TIMER_REG_OFFSET, }; struct arch_timer_context { From patchwork Wed Aug 4 08:58:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-23.5 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCCD5C43214 for ; Wed, 4 Aug 2021 08:58:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B890161040 for ; Wed, 4 Aug 2021 08:58:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236855AbhHDI7F (ORCPT ); Wed, 4 Aug 2021 04:59:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236853AbhHDI7D (ORCPT ); Wed, 4 Aug 2021 04:59:03 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2FA79C0617A1 for ; Wed, 4 Aug 2021 01:58:51 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id j21-20020a25d2150000b029057ac4b4e78fso2260893ybg.4 for ; Wed, 04 Aug 2021 01:58:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=kDlmZ2q+VtsAE3exEj8aYy6Fk3kSky3TCXUK2+oaNSo=; b=lzMCH9i930DInyi3TgFPeE0uphR3Msy4pTrV5RPcS66cl2mtNGs6v5FMcT24ugSCvu 9t2LTl5MeANnamFbgsOAhO26iTUlsALVuwLmAlCcO3GJ9l1hjsOAorK4kMvfpjtwNn0A BzurnpIA6EmR8GyK1/kV3LTsEcDNwzJRnnugFj0EUJxJYPmqNanYRpUqh9Iho74VI27e Za6PQgbIG636DV/zsqE46glgJvckLVfEpvZwIfocJHgnxj1mN/9rtgCngqSXNiD/Gw/d kHmREJP/0WVtk9MY2zVUvznJ0l9KvXjtClvLNoYeMw2fOuBBfPoJ8QZKRd6CAiszFLAJ PK5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=kDlmZ2q+VtsAE3exEj8aYy6Fk3kSky3TCXUK2+oaNSo=; b=U3fvBLsxUHsoJ4QhSWLKK9HDmtlN+gkU9QKYJE8Wsmscts5ZXdHhKtWBelJi5tnjOJ lyPGhresyaMLHY99HH95B4ap5yV9Z3VT2GQuZGdkKcIcXGmPs1RKFnAS685XeyrkK4VY wwyl5+gVnRE51+M2iRwz148aOf0hg7HGZ/HoxMzsNugT6dT7YOcvovabR1SnS1Esm1I4 h7/aCwk3xupY3+V6wMODHDTb/qaEB4pCBqDN3lv+OuNfV9VLrexwWkX6FY3HpA9pE6O9 IKw9imQ8r+E+TR5DooNwpGLCKHSuslOFFe3g6CFuTgdQ/Wa+iHOGv0jloYxXYmjMTGxj lyKA== X-Gm-Message-State: AOAM531CdPkuA4CQ2qCgZ/MI3RW5al7Uy/GjKeORkWLI8d3c1T2CoEtE XtA49yLrd8JPZ7I7ynMAtASxD6QfZHS7BeD9TpLHj2pJ+Wy3TpbjVegQVqoQt5UJGSMMpoLJOI5 1QDg6kZvtE7xv0kFX/WbCklqIiNuoqFXC7LTg5hTVvANYrvi4iUh/8ZwC8g== X-Google-Smtp-Source: ABdhPJwoa+pdRQxhpipLNFgpIp6Y6GN/h2wf96Y41BJ+I1JnXOOC4/K6kyDAjQKCzkOIoOhBQEk5G+hqcxc= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a25:be48:: with SMTP id d8mr33406835ybm.521.1628067530295; Wed, 04 Aug 2021 01:58:50 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:12 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-15-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 14/21] selftests: KVM: Add helper to check for register presence From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The KVM_GET_REG_LIST vCPU ioctl returns a list of supported registers for a given vCPU. Add a helper to check if a register exists in the list of supported registers. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- .../testing/selftests/kvm/include/kvm_util.h | 2 ++ tools/testing/selftests/kvm/lib/kvm_util.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index 1b3ef5757819..077082dd2ca7 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -215,6 +215,8 @@ void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu); void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu); + +bool vcpu_has_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t reg_id); void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg); void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg); #ifdef __KVM_HAVE_VCPU_EVENTS diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 0fe66ca6139a..a5801d4ed37d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1823,6 +1823,25 @@ void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu) ret, errno, strerror(errno)); } +bool vcpu_has_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t reg_id) +{ + struct kvm_reg_list *list; + bool ret = false; + uint64_t i; + + list = vcpu_get_reg_list(vm, vcpuid); + + for (i = 0; i < list->n; i++) { + if (list->reg[i] == reg_id) { + ret = true; + break; + } + } + + free(list); + return ret; +} + void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg) { int ret; From patchwork Wed Aug 4 08:58:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418143 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 781C4C4320E for ; Wed, 4 Aug 2021 08:58:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5FACA61078 for ; Wed, 4 Aug 2021 08:58:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236898AbhHDI7H (ORCPT ); Wed, 4 Aug 2021 04:59:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236871AbhHDI7E (ORCPT ); Wed, 4 Aug 2021 04:59:04 -0400 Received: from mail-oi1-x24a.google.com (mail-oi1-x24a.google.com [IPv6:2607:f8b0:4864:20::24a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A7AFC0613D5 for ; Wed, 4 Aug 2021 01:58:52 -0700 (PDT) Received: by mail-oi1-x24a.google.com with SMTP id n2-20020aca40020000b029025c9037b7faso815453oia.14 for ; Wed, 04 Aug 2021 01:58:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Wr2QUWPIrNr02r9ZSQ6a6WvFSF+P+rF7IWMFJFIeT5Q=; b=A2eaQevcuk1kE8kH+hNfVeiJGxQGIsvPPXH7dwJX1I1bqzmceDdLvtt3vtZsSlfHgS 6uk2fnUUV1bWg9ui/diKwA4nuUWGnCfjSPratLEZd7BP/7MO8akAcoc9w+EQ/wtsAXAp ZyNGkKQCPzWCb6fjuunbxbUeHNOvYwMVhCRqWRcU2+VYhha6puKXBjme8zME+4pwl6Bk TcuhrWi5b2xsYj1XFDIS6BErZBNJ2MwSHwcl0Oh6rDaqMeEyEhpsccRugDvMtCKPZdV8 RqjprVlUgFZUxBZHsKv+zbjtLGxLp/H0em+JFSda46mXMaNqevbjZdwKZHvUvVK5VorB lOwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Wr2QUWPIrNr02r9ZSQ6a6WvFSF+P+rF7IWMFJFIeT5Q=; b=FZ6BVo4VRIe2pyK+uk3EAnKmaY0MtHJDJ3BKZQjkodm8Rn360arxF5OtNtxGrZzRzy KWxichFRPJc+2cM5MW2L1MmJ+tKAr0sAjY2YAAXkC4qi0u3lj0kwqbYbd1NUKXBOKkeC R2rSP6+B7h9M1xe9qIMTEfj+/bUmt/D0pCPDyY7WCD3yVuxyUPzRappRo6zYqALIu9XX Fd9LbTkqtmeq2pod5h2+Qy9S0vJuGqMyjRoHHS0j5LJ3u1Rgsk21Nk5crSrT+knsoZ5s ukfbi7hroINoRcZataZTQTIGKo6uyqG14xBQj4plHJwsvZ1Q65oo4HH6Ehxe+ZecfR+r lwPg== X-Gm-Message-State: AOAM533/4JDzL+rMvn1RcMs23oZMbWVZt6fuo42lNeC43IGwUY8dICkf Dqm9tLo+cB4sgDdDYu2fp7uelpQ5N0ymubwU/5NIjtP2uaVTkx1zF6gqE3JVxx9ziFVsd5MwtDP g82ciEtuwLPRyE0CFRqovqedvN/RIu4qvMFhoCQ5GR/QzJxO/s9CX/Qt0uw== X-Google-Smtp-Source: ABdhPJwV6z5/wOQcC6ysoCIBRHVz7QoiKO1NC+BeHz63h1lYVDEtDeBmgg3mO02si6II7kJcePnt4XlEnxs= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a9d:6d16:: with SMTP id o22mr5444656otp.336.1628067531365; Wed, 04 Aug 2021 01:58:51 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:13 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-16-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 15/21] selftests: KVM: Add support for aarch64 to system_counter_offset_test From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org KVM/arm64 now allows userspace to adjust the guest virtual counter-timer via a vCPU register. Test that changes to the virtual counter-timer offset result in the correct view being presented to the guest. Reviewed-by: Andrew Jones Signed-off-by: Oliver Upton --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/aarch64/processor.h | 12 ++++ .../kvm/system_counter_offset_test.c | 56 ++++++++++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 9f7060c02668..fab42e7c23ee 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -98,6 +98,7 @@ TEST_GEN_PROGS_aarch64 += kvm_page_table_test TEST_GEN_PROGS_aarch64 += set_memory_region_test TEST_GEN_PROGS_aarch64 += steal_time TEST_GEN_PROGS_aarch64 += kvm_binary_stats_test +TEST_GEN_PROGS_aarch64 += system_counter_offset_test TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/resets diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index 27dc5c2e56b9..3168cdbae6ee 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -129,4 +129,16 @@ void vm_install_sync_handler(struct kvm_vm *vm, #define isb() asm volatile("isb" : : : "memory") +static inline uint64_t read_cntvct_ordered(void) +{ + uint64_t r; + + __asm__ __volatile__("isb\n\t" + "mrs %0, cntvct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/system_counter_offset_test.c b/tools/testing/selftests/kvm/system_counter_offset_test.c index b337bbbfa41f..ac933db83d03 100644 --- a/tools/testing/selftests/kvm/system_counter_offset_test.c +++ b/tools/testing/selftests/kvm/system_counter_offset_test.c @@ -53,7 +53,61 @@ static uint64_t host_read_guest_system_counter(struct test_case *test) return rdtsc() + test->tsc_offset; } -#else /* __x86_64__ */ +#elif __aarch64__ /* __x86_64__ */ + +enum arch_counter { + VIRTUAL, +}; + +struct test_case { + enum arch_counter counter; + uint64_t offset; +}; + +static struct test_case test_cases[] = { + { .counter = VIRTUAL, .offset = 0 }, + { .counter = VIRTUAL, .offset = 180 * NSEC_PER_SEC }, + { .counter = VIRTUAL, .offset = -180 * NSEC_PER_SEC }, +}; + +static void check_preconditions(struct kvm_vm *vm) +{ + if (vcpu_has_reg(vm, VCPU_ID, KVM_REG_ARM_TIMER_OFFSET)) + return; + + print_skip("KVM_REG_ARM_TIMER_OFFSET not supported; skipping test"); + exit(KSFT_SKIP); +} + +static void setup_system_counter(struct kvm_vm *vm, struct test_case *test) +{ + struct kvm_one_reg reg = { + .id = KVM_REG_ARM_TIMER_OFFSET, + .addr = (__u64)&test->offset, + }; + + vcpu_set_reg(vm, VCPU_ID, ®); +} + +static uint64_t guest_read_system_counter(struct test_case *test) +{ + switch (test->counter) { + case VIRTUAL: + return read_cntvct_ordered(); + default: + GUEST_ASSERT(0); + } + + /* unreachable */ + return 0; +} + +static uint64_t host_read_guest_system_counter(struct test_case *test) +{ + return read_cntvct_ordered() - test->offset; +} + +#else /* __aarch64__ */ #error test not implemented for this architecture! From patchwork Wed Aug 4 08:58:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418145 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF709C4338F for ; Wed, 4 Aug 2021 08:58:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9A18061073 for ; Wed, 4 Aug 2021 08:58:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236865AbhHDI7I (ORCPT ); Wed, 4 Aug 2021 04:59:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35162 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236863AbhHDI7F (ORCPT ); Wed, 4 Aug 2021 04:59:05 -0400 Received: from mail-qv1-xf4a.google.com (mail-qv1-xf4a.google.com [IPv6:2607:f8b0:4864:20::f4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CD67C0613D5 for ; Wed, 4 Aug 2021 01:58:53 -0700 (PDT) Received: by mail-qv1-xf4a.google.com with SMTP id u11-20020ad45aab0000b029033e289c093aso1294470qvg.10 for ; Wed, 04 Aug 2021 01:58:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=h8C+AkSSxjD2I6RXdGSsBwEWeDSTzFjVwyFJmn30s0c=; b=vdFpyj+9XNPjdYnHOx6TwDyWXfkwfTUZA5Sw6ri/Z+MfoVjX9B5ei1iIA6qchNTckg Js4/woRxok9rGl937dT5UR6w8jykMhwsS++V75ZeD8wlloCL6wCsYKsehUNaIOE43JeR Z2I0iFTOk5qzEKQKx3u2dbLLBMotmDxqqKCR94OqjLYyygFGecaxna6m9TnnTENZ1dlO BcCV64E3066DzzNmcmkPW3oPneJUjkCGeWxgt3hXPaU/8EVSRFSD6lZNyz1DT33Lkoi7 qZmZBVlnNgK5BwZRYc/LHdxEGICI0QBX432vw8WwyIBzzYfANL3FddNoQdY4qIW6LGFV epqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=h8C+AkSSxjD2I6RXdGSsBwEWeDSTzFjVwyFJmn30s0c=; b=G4v2mRAdLq1jIkjxb1oWOaQ3Ogawn/gDdoGTnrut+Zsdz5tDJpUZrM7Y1ML+7hg8ZR 3cm+R3T9Xby9/INUIPzuDMIYI29im1Gja3G0X1Iy4nMNe6K8Pxhh9sdj+SiVg39NwCxh KkheJxJjpEt3swGI5u4Id1JS3nPrUulsJ09EA9B5T6JA6s3YaMGYJkFV2ylDRBKmON9C othjTuyjg9gI2Jxg4F4I3ttOEsBm7Yu8zWCFu+VHymzhabQbGI2pke5MNAXMzS4CyfJF vfbGhvIjj9ScJ8E7+vuteDChfKSDvjsLtj5slvaZLWSLLpsclJOK+CsXUJZhxoT2WAsn Daxg== X-Gm-Message-State: AOAM532rj5k+v8Z7ClZHkOJ0kiFteH4iOwC0wMgev+akqNdnugsw9FDU 0B6reW/DcxzLx93HC6MghY4jhXTID4tPNfF92+AZB+79/+/Cph9RYNuRve3XYVrVSmsF+NVZj2S aN3P4JPU216I536YyVcfuobNd/6rwJfbBXtofoIr44whzNwkTbr0VKz5h5Q== X-Google-Smtp-Source: ABdhPJx+GeA32n6jMUHsP7WogSpQpinH4eyTOFkLIo8qvlVC8zogWUDIRuiTAtVqSj3R5xgXeAPAlnAcOpw= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6214:134c:: with SMTP id b12mr24474131qvw.39.1628067532459; Wed, 04 Aug 2021 01:58:52 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:14 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-17-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 16/21] arm64: cpufeature: Enumerate support for Enhanced Counter Virtualization From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce a new cpucap to indicate if the system supports full enhanced counter virtualization (i.e. ID_AA64MMFR0_EL1.ECV==0x2). Signed-off-by: Oliver Upton --- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kernel/cpufeature.c | 10 ++++++++++ arch/arm64/tools/cpucaps | 1 + 3 files changed, 13 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 7b9c3acba684..4dfc44066dfb 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -847,6 +847,8 @@ #define ID_AA64MMFR0_ASID_SHIFT 4 #define ID_AA64MMFR0_PARANGE_SHIFT 0 +#define ID_AA64MMFR0_ECV_VIRT 0x1 +#define ID_AA64MMFR0_ECV_PHYS 0x2 #define ID_AA64MMFR0_TGRAN4_NI 0xf #define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0 #define ID_AA64MMFR0_TGRAN64_NI 0xf diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 0ead8bfedf20..94c349e179d3 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -2301,6 +2301,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = has_cpuid_feature, .min_field_value = 1, }, + { + .desc = "Enhanced Counter Virtualization (Physical)", + .capability = ARM64_ECV, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .sys_reg = SYS_ID_AA64MMFR0_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64MMFR0_ECV_SHIFT, + .matches = has_cpuid_feature, + .min_field_value = ID_AA64MMFR0_ECV_PHYS, + }, {}, }; diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps index 49305c2e6dfd..d819ea614da5 100644 --- a/arch/arm64/tools/cpucaps +++ b/arch/arm64/tools/cpucaps @@ -3,6 +3,7 @@ # Internal CPU capabilities constants, keep this list sorted BTI +ECV # Unreliable: use system_supports_32bit_el0() instead. HAS_32BIT_EL0_DO_NOT_USE HAS_32BIT_EL1 From patchwork Wed Aug 4 08:58:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C217C4338F for ; Wed, 4 Aug 2021 08:59:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1470D60FC4 for ; Wed, 4 Aug 2021 08:59:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236904AbhHDI7K (ORCPT ); Wed, 4 Aug 2021 04:59:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35166 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236859AbhHDI7G (ORCPT ); Wed, 4 Aug 2021 04:59:06 -0400 Received: from mail-oi1-x249.google.com (mail-oi1-x249.google.com [IPv6:2607:f8b0:4864:20::249]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3DAC1C061798 for ; Wed, 4 Aug 2021 01:58:54 -0700 (PDT) Received: by mail-oi1-x249.google.com with SMTP id p84-20020acabf570000b029026702f1769bso277712oif.10 for ; Wed, 04 Aug 2021 01:58:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=kFwwMIpnmqOzxqT89bHMdsWlLDW/5PXBmoq4iDX0eaw=; b=YIwgyuXhvqVBtX51VOKKk6u9LfEBspNfXwujueAbUBIapLhehiLsFrngx90jPYlEe9 MB5ElPvTBNd+uIi+Mav5Qz+f0sZKbUN56TcZ4zNiAbkwg/DPcedQrhv+zLaCD8v60aYf MnOo8w3Z4/a7gRNM01oLHeVFvqqfcO0Gh7bwOrIeAr0Wao/Qiq8u+/WTZ066EmNi50oY XMLZm/ixZ+hiG3rYwV2OMFjFYPka7EglMBj4lnueqeMmTVnWXHp/Wi249rvt/2e2jqex jyZWEPMpVub8y1UOH8F6ERXSvOItCs7DkmwAIzr1fvO7ij9w9aDm/qGwGLYDmHJt2aNn qegQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=kFwwMIpnmqOzxqT89bHMdsWlLDW/5PXBmoq4iDX0eaw=; b=tspyxkkwlcLhLwAHwJSx6KmWlS/WHMAqHAck0HHb+yuRxydlSZXKr1YZ5HfWmgU9zs lCUO5cuQRKBzhmgkIoexy4rNgJtUsc6RGbLmojYDwDySWFT78B4sIY68Yh4Imh+5y6jk WdxnHn7szPKWQ7TOjtxgirV3sjcShaamfqOCFjfZPSDMgO3ynqlKoCBIeVQNPGfi9xCm xmaZkGW04sZfT1etywsh1lk+DIlSEvDEWQ9lHtpdvYYSdp16Mad1But4vJcLcSZkPhHs n9iGrElCK1JGK2zKVg0R00CDfp6ZO2D/rRF6ZrB1gbleiWLb9nL2AWuJyAoYmekLWI9l vwxw== X-Gm-Message-State: AOAM533udApMyXDAzuXPW5VPlmkkNJ1FeNd1v/kL+7Wxsq2OeRKKC1WN nkpKgsthL9bazTgSbiV/1RsekVkyobhQACIBlR2+ZCNFGGyGufdfRPcy97nM2jlyK1joyAt4fbT L+pAMHbBg2NNvWnPXkLAlsZJ2a5v84SZGLcLmnoGhcvyRxxTmLsgsNQnpoA== X-Google-Smtp-Source: ABdhPJyuAtu1rbFc6HpuHaUiO2dj+fadWoeHL9t28wgyqqRe/01oBpVK787LMhXlOFyahOuzSrGIK043sC4= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:aca:6704:: with SMTP id z4mr17394391oix.89.1628067533524; Wed, 04 Aug 2021 01:58:53 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:15 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-18-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 17/21] KVM: arm64: Allow userspace to configure a guest's counter-timer offset From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Presently, KVM provides no facilities for correctly migrating a guest that depends on the physical counter-timer. Whie most guests (barring NV, of course) should not depend on the physical counter-timer, an operator may wish to provide a consistent view of the physical counter-timer across migrations. Provide userspace with a new vCPU attribute to modify the guest counter-timer offset. Unlike KVM_REG_ARM_TIMER_OFFSET, this attribute is hidden from the guest's architectural state. The value offsets *both* the virtual and physical counter-timer views for the guest. Only support this attribute on ECV systems as ECV is required for hardware offsetting of the physical counter-timer. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- Documentation/virt/kvm/devices/vcpu.rst | 28 ++++++ arch/arm64/include/asm/kvm_asm.h | 2 + arch/arm64/include/asm/sysreg.h | 2 + arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/arch_timer.c | 122 +++++++++++++++++++++++- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 ++ arch/arm64/kvm/hyp/nvhe/timer-sr.c | 5 + arch/arm64/kvm/hyp/vhe/timer-sr.c | 5 + include/clocksource/arm_arch_timer.h | 1 + 9 files changed, 169 insertions(+), 3 deletions(-) diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst index 3b399d727c11..3ba35b9d9d03 100644 --- a/Documentation/virt/kvm/devices/vcpu.rst +++ b/Documentation/virt/kvm/devices/vcpu.rst @@ -139,6 +139,34 @@ configured values on other VCPUs. Userspace should configure the interrupt numbers on at least one VCPU after creating all VCPUs and before running any VCPUs. +2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_OFFSET +----------------------------------------- + +:Parameters: in kvm_device_attr.addr the address for the timer offset is a + pointer to a __u64 + +Returns: + + ======= ================================== + -EFAULT Error reading/writing the provided + parameter address + -ENXIO Timer offsetting not implemented + ======= ================================== + +Specifies the guest's counter-timer offset from the host's virtual counter. +The guest's physical counter value is then derived by the following +equation: + + guest_cntpct = host_cntvct - KVM_ARM_VCPU_TIMER_OFFSET + +The guest's virtual counter value is derived by the following equation: + + guest_cntvct = host_cntvct - KVM_REG_ARM_TIMER_OFFSET + - KVM_ARM_VCPU_TIMER_OFFSET + +KVM does not allow the use of varying offset values for different vCPUs; +the last written offset value will be broadcasted to all vCPUs in a VM. + 3. GROUP: KVM_ARM_VCPU_PVTIME_CTRL ================================== diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 9f0bf2109be7..ab1c8fdb0177 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -65,6 +65,7 @@ #define __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize 19 #define __KVM_HOST_SMCCC_FUNC___pkvm_mark_hyp 20 #define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 21 +#define __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntpoff 22 #ifndef __ASSEMBLY__ @@ -200,6 +201,7 @@ extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa, extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); extern void __kvm_timer_set_cntvoff(u64 cntvoff); +extern void __kvm_timer_set_cntpoff(u64 cntpoff); extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 4dfc44066dfb..c34672aa65b9 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -586,6 +586,8 @@ #define SYS_ICH_LR14_EL2 __SYS__LR8_EL2(6) #define SYS_ICH_LR15_EL2 __SYS__LR8_EL2(7) +#define SYS_CNTPOFF_EL2 sys_reg(3, 4, 14, 0, 6) + /* VHE encodings for architectural EL0/1 system registers */ #define SYS_SCTLR_EL12 sys_reg(3, 5, 1, 0, 0) #define SYS_CPACR_EL12 sys_reg(3, 5, 1, 0, 2) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 949a31bc10f0..15150f8224a1 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -366,6 +366,7 @@ struct kvm_arm_copy_mte_tags { #define KVM_ARM_VCPU_TIMER_CTRL 1 #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 +#define KVM_ARM_VCPU_TIMER_OFFSET 2 #define KVM_ARM_VCPU_PVTIME_CTRL 2 #define KVM_ARM_VCPU_PVTIME_IPA 0 diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index a8815b09da3e..f15058612994 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -85,11 +85,15 @@ u64 timer_get_cval(struct arch_timer_context *ctxt) static u64 timer_get_offset(struct arch_timer_context *ctxt) { struct kvm_vcpu *vcpu = ctxt->vcpu; + struct arch_timer_cpu *timer = vcpu_timer(vcpu); switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: + case TIMER_PTIMER: return ctxt->host_offset; default: + WARN_ONCE(1, "unrecognized timer %ld\n", + arch_timer_ctx_index(ctxt)); return 0; } } @@ -144,6 +148,7 @@ static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: + case TIMER_PTIMER: ctxt->host_offset = offset; break; default: @@ -572,6 +577,11 @@ static void set_cntvoff(u64 cntvoff) kvm_call_hyp(__kvm_timer_set_cntvoff, cntvoff); } +static void set_cntpoff(u64 cntpoff) +{ + kvm_call_hyp(__kvm_timer_set_cntpoff, cntpoff); +} + static inline void set_timer_irq_phys_active(struct arch_timer_context *ctx, bool active) { int r; @@ -647,6 +657,8 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) } set_cntvoff(timer_get_offset(map.direct_vtimer)); + if (cpus_have_const_cap(ARM64_ECV)) + set_cntpoff(timer_get_offset(vcpu_ptimer(vcpu))); kvm_timer_unblocking(vcpu); @@ -814,6 +826,22 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) mutex_unlock(&kvm->lock); } +static void update_ptimer_cntpoff(struct kvm_vcpu *vcpu, u64 cntpoff) +{ + struct kvm *kvm = vcpu->kvm; + u64 cntvoff; + + mutex_lock(&kvm->lock); + + /* adjustments to the physical offset also affect vtimer */ + cntvoff = timer_get_offset(vcpu_vtimer(vcpu)); + cntvoff += cntpoff - timer_get_offset(vcpu_ptimer(vcpu)); + + update_timer_offset(vcpu, TIMER_PTIMER, cntpoff, false); + update_timer_offset(vcpu, TIMER_VTIMER, cntvoff, false); + mutex_unlock(&kvm->lock); +} + void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = vcpu_timer(vcpu); @@ -932,6 +960,29 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) return (u64)-1; } +/** + * kvm_arm_timer_read_offset - returns the guest value of CNTVOFF_EL2. + * @vcpu: the vcpu pointer + * + * Computes the guest value of CNTVOFF_EL2 by subtracting the physical + * counter offset. Note that KVM defines CNTVOFF_EL2 as the offset from the + * guest's physical counter-timer, not the host's. + * + * Returns: the guest value for CNTVOFF_EL2 + */ +static u64 kvm_arm_timer_read_offset(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + u64 offset; + + mutex_lock(&kvm->lock); + offset = timer_get_offset(vcpu_vtimer(vcpu)) - + timer_get_offset(vcpu_ptimer(vcpu)); + mutex_unlock(&kvm->lock); + + return offset; +} + static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, struct arch_timer_context *timer, enum kvm_arch_timer_regs treg) @@ -957,7 +1008,7 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, break; case TIMER_REG_OFFSET: - val = timer_get_offset(timer); + val = kvm_arm_timer_read_offset(vcpu); break; default: @@ -1350,6 +1401,9 @@ void kvm_timer_init_vhe(void) val = read_sysreg(cnthctl_el2); val |= (CNTHCTL_EL1PCEN << cnthctl_shift); val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); + + if (cpus_have_const_cap(ARM64_ECV)) + val |= CNTHCTL_ECV; write_sysreg(val, cnthctl_el2); } @@ -1364,7 +1418,8 @@ static void set_timer_irqs(struct kvm *kvm, int vtimer_irq, int ptimer_irq) } } -int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +static int kvm_arm_timer_set_attr_irq(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) { int __user *uaddr = (int __user *)(long)attr->addr; struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); @@ -1397,7 +1452,37 @@ int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) return 0; } -int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +static int kvm_arm_timer_set_attr_offset(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + u64 __user *uaddr = (u64 __user *)(long)attr->addr; + u64 offset; + + if (!cpus_have_const_cap(ARM64_ECV)) + return -ENXIO; + + if (get_user(offset, uaddr)) + return -EFAULT; + + update_ptimer_cntpoff(vcpu, offset); + return 0; +} + +int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: + case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: + return kvm_arm_timer_set_attr_irq(vcpu, attr); + case KVM_ARM_VCPU_TIMER_OFFSET: + return kvm_arm_timer_set_attr_offset(vcpu, attr); + default: + return -ENXIO; + } +} + +static int kvm_arm_timer_get_attr_irq(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) { int __user *uaddr = (int __user *)(long)attr->addr; struct arch_timer_context *timer; @@ -1418,12 +1503,43 @@ int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) return put_user(irq, uaddr); } +static int kvm_arm_timer_get_attr_offset(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + u64 __user *uaddr = (u64 __user *)(long)attr->addr; + u64 offset; + + if (!cpus_have_const_cap(ARM64_ECV)) + return -ENXIO; + + offset = timer_get_offset(vcpu_ptimer(vcpu)); + return put_user(offset, uaddr); +} + +int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: + case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: + return kvm_arm_timer_get_attr_irq(vcpu, attr); + case KVM_ARM_VCPU_TIMER_OFFSET: + return kvm_arm_timer_get_attr_offset(vcpu, attr); + default: + return -ENXIO; + } +} + int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { switch (attr->attr) { case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: return 0; + case KVM_ARM_VCPU_TIMER_OFFSET: + if (cpus_have_const_cap(ARM64_ECV)) + return 0; + break; } return -ENXIO; diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 1632f001f4ed..cfa923df3af6 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -68,6 +68,11 @@ static void handle___kvm_timer_set_cntvoff(struct kvm_cpu_context *host_ctxt) __kvm_timer_set_cntvoff(cpu_reg(host_ctxt, 1)); } +static void handle___kvm_timer_set_cntpoff(struct kvm_cpu_context *host_ctxt) +{ + __kvm_timer_set_cntpoff(cpu_reg(host_ctxt, 1)); +} + static void handle___kvm_enable_ssbs(struct kvm_cpu_context *host_ctxt) { u64 tmp; @@ -197,6 +202,7 @@ static const hcall_t host_hcall[] = { HANDLE_FUNC(__pkvm_create_private_mapping), HANDLE_FUNC(__pkvm_prot_finalize), HANDLE_FUNC(__pkvm_mark_hyp), + HANDLE_FUNC(__kvm_timer_set_cntpoff), }; static void handle_host_hcall(struct kvm_cpu_context *host_ctxt) diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c index 9072e71693ba..5b8b4cd02506 100644 --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c @@ -15,6 +15,11 @@ void __kvm_timer_set_cntvoff(u64 cntvoff) write_sysreg(cntvoff, cntvoff_el2); } +void __kvm_timer_set_cntpoff(u64 cntpoff) +{ + write_sysreg_s(cntpoff, SYS_CNTPOFF_EL2); +} + /* * Should only be called on non-VHE systems. * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). diff --git a/arch/arm64/kvm/hyp/vhe/timer-sr.c b/arch/arm64/kvm/hyp/vhe/timer-sr.c index 4cda674a8be6..231e16a071a5 100644 --- a/arch/arm64/kvm/hyp/vhe/timer-sr.c +++ b/arch/arm64/kvm/hyp/vhe/timer-sr.c @@ -10,3 +10,8 @@ void __kvm_timer_set_cntvoff(u64 cntvoff) { write_sysreg(cntvoff, cntvoff_el2); } + +void __kvm_timer_set_cntpoff(u64 cntpoff) +{ + write_sysreg_s(cntpoff, SYS_CNTPOFF_EL2); +} diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index 73c7139c866f..7252ffa3d675 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -21,6 +21,7 @@ #define CNTHCTL_EVNTEN (1 << 2) #define CNTHCTL_EVNTDIR (1 << 3) #define CNTHCTL_EVNTI (0xF << 4) +#define CNTHCTL_ECV (1 << 12) enum arch_timer_reg { ARCH_TIMER_REG_CTRL, From patchwork Wed Aug 4 08:58:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B0B7C4320A for ; Wed, 4 Aug 2021 08:59:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3992C60FC4 for ; Wed, 4 Aug 2021 08:59:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236939AbhHDI7M (ORCPT ); Wed, 4 Aug 2021 04:59:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35172 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236871AbhHDI7I (ORCPT ); Wed, 4 Aug 2021 04:59:08 -0400 Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3F71C0613D5 for ; Wed, 4 Aug 2021 01:58:55 -0700 (PDT) Received: by mail-qt1-x84a.google.com with SMTP id h18-20020ac856920000b029025eb726dd9bso747410qta.8 for ; Wed, 04 Aug 2021 01:58:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=xEsi9T4OqglNe742KkivPaDxPwp3ZoFaFAtWROXbBVo=; b=ChSZQBwkJB66ulFJ3pUxF49mjFQq4MBi3vZvx3rv+9LE+Wi7bTs1eRJQzexlr+JRSY n8GGWqtHE6Gj0UzXp8u7OVcee5UjmtXgNekWCLLa5kYlfHloNwdxCdc+Ct0rKHZ9H5MS Lkfrmt/805DmNFA9xjBhD6iryqm8HFC8yEIAfGsd6QT62XFkkQdbUnqv+KeQRQQcaoKc ooADx9GQgfZmou14MKEHG/t4rhEESUtzhs6w4fmnvAlQZTc1x6TOFShLv0Ltd4CyQ4mp W5tQu0tDthrEE4M9igHoxYjuLR+gA4eHJ/5/Iob0qnQunOUx/bJFNJrWm1phkPrntUr2 kgbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=xEsi9T4OqglNe742KkivPaDxPwp3ZoFaFAtWROXbBVo=; b=La8/gsP9SY7aA8dKh9DsYIRUOzqbP5dFCFQpnX9tSTs75YOyRRgTrba/RJzN+0EVom OfZNWp4iF3fFf/kIuV5+hP2ttT5k9Su5oTSwmthIEZFAyKqVUuvzEoC3l7HTeqf/a+Ix D05Y+Sa2Bn5/tvxb6sZc3EN38gLdzkXowXZSeL9BkoBjZgawmlZn7EsSlwB1TYMSgXxE e5AcNaX8iH09O9RQZhv40O4sQ3q1lCBZQhsl0sJC9LtFLEZJadNTnap77UjsMgavci1V fgQkNSM/xTv5jg6Qrpe50eZBGusc0JDTtwtMJmD0R2m6fq8sS9XhUy0hUlgJLxgdmX8G FOgg== X-Gm-Message-State: AOAM531lEIR6kXTZQa5XJqS79g53m8dFFuSWETCfUWJkC9WfdKx3j7AN Tvpr9gbfc4Qr5FmaktqAWmPCJ52HWutV+m3KOO9ZPMeB5hntuem/ConYt69VKiGNAmhC92UmIli eSq+7sp9LUAGbq+Q0TcxQlk1D8P1InTUMtDtiEpBthXc6CBAfJtBa7AVlLg== X-Google-Smtp-Source: ABdhPJw4uOQBnarbZ8Pq5S9gvLmcNwTMIjaIMpvh+qw/OSoRZsXJkePXii8fJVoN7ZA8FRpp8uLdyyoJ81g= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6214:104b:: with SMTP id l11mr25726502qvr.40.1628067534598; Wed, 04 Aug 2021 01:58:54 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:16 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-19-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 18/21] KVM: arm64: Configure timer traps in vcpu_load() for VHE From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org In preparation for emulated physical counter-timer offsetting, configure traps on every vcpu_load() for VHE systems. As before, these trap settings do not affect host userspace, and are only active for the guest. Suggested-by: Marc Zyngier Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- arch/arm64/kvm/arch_timer.c | 10 +++++++--- arch/arm64/kvm/arm.c | 4 +--- include/kvm/arm_arch_timer.h | 2 -- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index f15058612994..9ead94aa867d 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -51,6 +51,7 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu, static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, struct arch_timer_context *timer, enum kvm_arch_timer_regs treg); +static void kvm_timer_enable_traps_vhe(void); u32 timer_get_ctl(struct arch_timer_context *ctxt) { @@ -668,6 +669,9 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) if (map.emul_ptimer) timer_emulate(map.emul_ptimer); + + if (has_vhe()) + kvm_timer_enable_traps_vhe(); } bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu) @@ -1383,12 +1387,12 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) } /* - * On VHE system, we only need to configure the EL2 timer trap register once, - * not for every world switch. + * On VHE system, we only need to configure the EL2 timer trap register on + * vcpu_load(), but not every world switch into the guest. * The host kernel runs at EL2 with HCR_EL2.TGE == 1, * and this makes those bits have no effect for the host kernel execution. */ -void kvm_timer_init_vhe(void) +static void kvm_timer_enable_traps_vhe(void) { /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ u32 cnthctl_shift = 10; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index e9a2b8f27792..47ea1e1ba80b 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1558,9 +1558,7 @@ static void cpu_hyp_reinit(void) cpu_hyp_reset(); - if (is_kernel_in_hyp_mode()) - kvm_timer_init_vhe(); - else + if (!is_kernel_in_hyp_mode()) cpu_init_hyp_mode(); cpu_set_hyp_vector(); diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 615f9314f6a5..254653b42da0 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -87,8 +87,6 @@ u64 kvm_phys_timer_read(void); void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu); void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); -void kvm_timer_init_vhe(void); - bool kvm_arch_timer_get_input_level(int vintid); #define vcpu_timer(v) (&(v)->arch.timer_cpu) From patchwork Wed Aug 4 08:58:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418151 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94065C43214 for ; Wed, 4 Aug 2021 08:59:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8210E60F8F for ; Wed, 4 Aug 2021 08:59:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236871AbhHDI7R (ORCPT ); Wed, 4 Aug 2021 04:59:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236862AbhHDI7I (ORCPT ); Wed, 4 Aug 2021 04:59:08 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76D9CC06179B for ; Wed, 4 Aug 2021 01:58:56 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id b9-20020a5b07890000b0290558245b7eabso2258865ybq.10 for ; Wed, 04 Aug 2021 01:58:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=5F2XBId6Ml8d60ozFayhTnFPlnF21xMQYH0bLBzTlnY=; b=P/k5j1VS70sB8KLubXHq8/9bo8zjwK2ApmesXmWhSfReRNFGLt7FgvYu9pxbL6CMou jqHRyYf9SLnUjdLKJDC/uGZe+5hsYe27lfpfmoaEpKXJ0DV/3X4nK9CLFDBUyABhnYLK 0Z44gI8AjTXpmoIvCKRNQDfMcuTKGA36vz7aezWaRVzygXDtNs0MdO82Vja0e+m9cry0 BVMfsfEVyxRXREMb1Kyb9F5T0WGSTugrH4X2p9veldb6WExGhuBbstJKbJKsQrdZ1+C2 CXxBgk3nuMutZaqFqkrD2cNUjfrbWvLYbbUJX+u9gb95Zb/lCrlxb2YcX179DIalG6bX kYow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=5F2XBId6Ml8d60ozFayhTnFPlnF21xMQYH0bLBzTlnY=; b=NHZLWl3igLdGFTmQIFBdyLLAz96gKL8SflfAhuRj3bEFgqgClOMvgLXcNE9VHjj4za 0vIs4CunqSGxMNcYSmF5WXnHQ57z4an0Q74ZvSiP02bmSoqR/8oT3BBkjR3SoPxONrNT lVB/ujjOs0lejEFvIPIwM3RTNvs05Q44KSWGT3MMhtcW5xN+4K2mfr4g/z/YRC41xgSu b85WH5yvJt6d0WrwGAVb8Zf+SGfsf/xrNT1IuPbr+DDHkzBIifQ2crdgg4rDOUEii4nr 2xJRa7IyQ6hoQ1ium26b4VR8s3r6yKZ4Z9fN/iGkMNNS8maVCqqdMdnNbfz8UeLHtH89 9VWA== X-Gm-Message-State: AOAM530IiHEDY0XQxbFsD4+cggHBWtWMV1iZRZLn7zQOFvRwaXUfTMn8 N6W9KYC0STAU8ZDB0f4nD/i6pr0XPrpINE5B33CuXLDdQ9m3xK1krth2yIegJs3YTIkPNcmwOfR HmOIWDtJXzk05PDLajBNe/G9JKCbzvX1MH8EHJ1YUh/uzYox5UbLi0esuXA== X-Google-Smtp-Source: ABdhPJyliD4AsBjXCLBTaK2m63jx3rCYhGHEqJklXaxkWK0zm/UKQW1pH50RYWgtA27P4BN9OFdyiRL9jr0= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a25:5844:: with SMTP id m65mr33677475ybb.199.1628067535625; Wed, 04 Aug 2021 01:58:55 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:17 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-20-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 19/21] KVM: arm64: Emulate physical counter offsetting on non-ECV systems From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Unfortunately, ECV hasn't yet arrived in any tangible hardware. At the same time, controlling the guest view of the physical counter-timer is useful. Support guest counter-timer offsetting on non-ECV systems by trapping guest accesses to the physical counter-timer. Emulate reads of the physical counter in the fast exit path. Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/arch_timer.c | 53 +++++++++++++++---------- arch/arm64/kvm/hyp/include/hyp/switch.h | 29 ++++++++++++++ arch/arm64/kvm/hyp/nvhe/timer-sr.c | 11 ++++- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index c34672aa65b9..e49790ae5da4 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -505,6 +505,7 @@ #define SYS_AMEVCNTR0_MEM_STALL SYS_AMEVCNTR0_EL0(3) #define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0) +#define SYS_CNTPCT_EL0 sys_reg(3, 3, 14, 0, 1) #define SYS_CNTP_TVAL_EL0 sys_reg(3, 3, 14, 2, 0) #define SYS_CNTP_CTL_EL0 sys_reg(3, 3, 14, 2, 1) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 9ead94aa867d..b7cb63acf2a0 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -51,7 +51,7 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu, static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, struct arch_timer_context *timer, enum kvm_arch_timer_regs treg); -static void kvm_timer_enable_traps_vhe(void); +static void kvm_timer_enable_traps_vhe(struct kvm_vcpu *vcpu); u32 timer_get_ctl(struct arch_timer_context *ctxt) { @@ -175,6 +175,12 @@ static void timer_set_guest_offset(struct arch_timer_context *ctxt, u64 offset) } } +static bool ptimer_emulation_required(struct kvm_vcpu *vcpu) +{ + return timer_get_offset(vcpu_ptimer(vcpu)) && + !cpus_have_const_cap(ARM64_ECV); +} + u64 kvm_phys_timer_read(void) { return timecounter->cc->read(timecounter->cc); @@ -184,8 +190,13 @@ static void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map) { if (has_vhe()) { map->direct_vtimer = vcpu_vtimer(vcpu); - map->direct_ptimer = vcpu_ptimer(vcpu); - map->emul_ptimer = NULL; + if (!ptimer_emulation_required(vcpu)) { + map->direct_ptimer = vcpu_ptimer(vcpu); + map->emul_ptimer = NULL; + } else { + map->direct_ptimer = NULL; + map->emul_ptimer = vcpu_ptimer(vcpu); + } } else { map->direct_vtimer = vcpu_vtimer(vcpu); map->direct_ptimer = NULL; @@ -671,7 +682,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) timer_emulate(map.emul_ptimer); if (has_vhe()) - kvm_timer_enable_traps_vhe(); + kvm_timer_enable_traps_vhe(vcpu); } bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu) @@ -1392,22 +1403,29 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) * The host kernel runs at EL2 with HCR_EL2.TGE == 1, * and this makes those bits have no effect for the host kernel execution. */ -static void kvm_timer_enable_traps_vhe(void) +static void kvm_timer_enable_traps_vhe(struct kvm_vcpu *vcpu) { /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ u32 cnthctl_shift = 10; - u64 val; + u64 val, mask; + + mask = CNTHCTL_EL1PCEN << cnthctl_shift; + mask |= CNTHCTL_EL1PCTEN << cnthctl_shift; - /* - * VHE systems allow the guest direct access to the EL1 physical - * timer/counter. - */ val = read_sysreg(cnthctl_el2); - val |= (CNTHCTL_EL1PCEN << cnthctl_shift); - val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); if (cpus_have_const_cap(ARM64_ECV)) val |= CNTHCTL_ECV; + + /* + * VHE systems allow the guest direct access to the EL1 physical + * timer/counter if offsetting isn't requested on a non-ECV system. + */ + if (ptimer_emulation_required(vcpu)) + val &= ~mask; + else + val |= mask; + write_sysreg(val, cnthctl_el2); } @@ -1462,9 +1480,6 @@ static int kvm_arm_timer_set_attr_offset(struct kvm_vcpu *vcpu, u64 __user *uaddr = (u64 __user *)(long)attr->addr; u64 offset; - if (!cpus_have_const_cap(ARM64_ECV)) - return -ENXIO; - if (get_user(offset, uaddr)) return -EFAULT; @@ -1513,9 +1528,6 @@ static int kvm_arm_timer_get_attr_offset(struct kvm_vcpu *vcpu, u64 __user *uaddr = (u64 __user *)(long)attr->addr; u64 offset; - if (!cpus_have_const_cap(ARM64_ECV)) - return -ENXIO; - offset = timer_get_offset(vcpu_ptimer(vcpu)); return put_user(offset, uaddr); } @@ -1539,11 +1551,8 @@ int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) switch (attr->attr) { case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: - return 0; case KVM_ARM_VCPU_TIMER_OFFSET: - if (cpus_have_const_cap(ARM64_ECV)) - return 0; - break; + return 0; } return -ENXIO; diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index e4a2f295a394..abd3813a709e 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -405,6 +406,31 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) return true; } +static inline u64 __timer_read_cntpct(struct kvm_vcpu *vcpu) +{ + return __arch_counter_get_cntpct() - vcpu_ptimer(vcpu)->host_offset; +} + +static inline bool __hyp_handle_counter(struct kvm_vcpu *vcpu) +{ + u32 sysreg; + int rt; + u64 rv; + + if (kvm_vcpu_trap_get_class(vcpu) != ESR_ELx_EC_SYS64) + return false; + + sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu)); + if (sysreg != SYS_CNTPCT_EL0) + return false; + + rt = kvm_vcpu_sys_get_rt(vcpu); + rv = __timer_read_cntpct(vcpu); + vcpu_set_reg(vcpu, rt, rv); + __kvm_skip_instr(vcpu); + return true; +} + /* * Return true when we were able to fixup the guest exit and should return to * the guest, false when we should restore the host state and return to the @@ -439,6 +465,9 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) if (*exit_code != ARM_EXCEPTION_TRAP) goto exit; + if (__hyp_handle_counter(vcpu)) + goto guest; + if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 && handle_tx2_tvm(vcpu)) diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c index 5b8b4cd02506..67236c2e0ba7 100644 --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c @@ -44,10 +44,17 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu) /* * Disallow physical timer access for the guest - * Physical counter access is allowed */ val = read_sysreg(cnthctl_el2); val &= ~CNTHCTL_EL1PCEN; - val |= CNTHCTL_EL1PCTEN; + + /* + * Disallow physical counter access for the guest if offsetting is + * requested on a non-ECV system. + */ + if (vcpu_ptimer(vcpu)->host_offset && !cpus_have_const_cap(ARM64_ECV)) + val &= ~CNTHCTL_EL1PCTEN; + else + val |= CNTHCTL_EL1PCTEN; write_sysreg(val, cnthctl_el2); } From patchwork Wed Aug 4 08:58:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418153 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BB3E0C4320A for ; Wed, 4 Aug 2021 08:59:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A34F760F02 for ; Wed, 4 Aug 2021 08:59:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236899AbhHDI7S (ORCPT ); Wed, 4 Aug 2021 04:59:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236894AbhHDI7K (ORCPT ); Wed, 4 Aug 2021 04:59:10 -0400 Received: from mail-qv1-xf4a.google.com (mail-qv1-xf4a.google.com [IPv6:2607:f8b0:4864:20::f4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7847EC06179C for ; Wed, 4 Aug 2021 01:58:57 -0700 (PDT) Received: by mail-qv1-xf4a.google.com with SMTP id b8-20020a0562141148b02902f1474ce8b7so1265458qvt.20 for ; Wed, 04 Aug 2021 01:58:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=P+wj7LgLjEuWRbpjKCXjEpBSkxsEIWcdrd+/OVNGjgQ=; b=U2RWOObCpS8DFZJ10Fp2o+XLbL0l1Du9Q2Q9GE9WrsZOYR4vwBJQlSHULYkGmuvObp qkHivooxec/DqyZKsQVcgoEPCJi+6nxBSJa++GLLq4UkYPeTO/PnhQU8BxXCanAd/n3b 1VAAXmzHLRgzm8XB6suWss1/HgHWX8AsDQjtvEEKe6uBRGu5tM62spN1T/IizoXmP1ZL /bcqtSUX18eaq6JGBkF1Jl6CZbI9tnVwffM2msHBTiN69mXBBWf9eO+ZEhofwM/eDIVc AgUFDx/s8u2xV/CUIjyX8OpmxWHZj6alRmINi+u/RPuPYEpQrLqUs/YiaPtSGXJY1Ysc UVRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=P+wj7LgLjEuWRbpjKCXjEpBSkxsEIWcdrd+/OVNGjgQ=; b=nrYK8sTztx5gnKMXXUExpgsvRCtwk08o+UW5218E/aofJNH4hgfnC1O/2wUIOVHOid 3Ws6jGrCWU68VSS5nLkFt+z1Q9hoOgmpSa8shXxYohdBvZWn10won1XtJR/kbxOS7Spc k9G1YsFaYK+ncqk+Msw/hymje9x+Shvp4BRgcX4gVtbM1wVOelcvowUR+gbnI3gyUyTx 430Y1PX1Nc/vf00SKBpCbzeW2BsFsyGaX/CX5DmHwMkIU3Gxb5e8qtIW66zmjM0b/KKM lo3skHq4hpRXr2f6AA1Xn/Q3HQ7Dxawn5yXEA9pNNwcQDsaocAm5VAMTVcuQ5vZN5/Jj 3mLQ== X-Gm-Message-State: AOAM532uOVAz2n7S2Bv7/xdiZdasnCnpP+U+9wYknB9FGh8kzANxkSho i+P3/h6UhMJYmM9PDBOGzVN6oBR1J4xxViHY6j5heQ6Ab1Wi7njvlufBRiyIglct2uhkkSF8BFK G50W28PxSIO/WEgfVbwFTczatykb0Z5KyyUvvkVGT1lqi0+3pY/mp6jCWbA== X-Google-Smtp-Source: ABdhPJxwuRb6Dx8CoyJvkFTha9TsHjRjV9Svfskn24Ka80JcxAcKjGHT4By5V5+EQXZYVffGDUwuCZ/2cFY= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a05:6214:e67:: with SMTP id jz7mr23858033qvb.0.1628067536659; Wed, 04 Aug 2021 01:58:56 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:18 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-21-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 20/21] selftests: KVM: Test physical counter offsetting From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Test that userspace adjustment of the guest physical counter-timer results in the correct view within the guest. Cc: Andrew Jones Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- .../selftests/kvm/include/aarch64/processor.h | 12 +++++++ .../kvm/system_counter_offset_test.c | 31 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index 3168cdbae6ee..7f53d90e9512 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -141,4 +141,16 @@ static inline uint64_t read_cntvct_ordered(void) return r; } +static inline uint64_t read_cntpct_ordered(void) +{ + uint64_t r; + + __asm__ __volatile__("isb\n\t" + "mrs %0, cntpct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/system_counter_offset_test.c b/tools/testing/selftests/kvm/system_counter_offset_test.c index ac933db83d03..82d26a45cc48 100644 --- a/tools/testing/selftests/kvm/system_counter_offset_test.c +++ b/tools/testing/selftests/kvm/system_counter_offset_test.c @@ -57,6 +57,9 @@ static uint64_t host_read_guest_system_counter(struct test_case *test) enum arch_counter { VIRTUAL, + PHYSICAL, + /* offset physical, read virtual */ + PHYSICAL_READ_VIRTUAL, }; struct test_case { @@ -68,32 +71,54 @@ static struct test_case test_cases[] = { { .counter = VIRTUAL, .offset = 0 }, { .counter = VIRTUAL, .offset = 180 * NSEC_PER_SEC }, { .counter = VIRTUAL, .offset = -180 * NSEC_PER_SEC }, + { .counter = PHYSICAL, .offset = 0 }, + { .counter = PHYSICAL, .offset = 180 * NSEC_PER_SEC }, + { .counter = PHYSICAL, .offset = -180 * NSEC_PER_SEC }, + { .counter = PHYSICAL_READ_VIRTUAL, .offset = 0 }, + { .counter = PHYSICAL_READ_VIRTUAL, .offset = 180 * NSEC_PER_SEC }, + { .counter = PHYSICAL_READ_VIRTUAL, .offset = -180 * NSEC_PER_SEC }, }; static void check_preconditions(struct kvm_vm *vm) { - if (vcpu_has_reg(vm, VCPU_ID, KVM_REG_ARM_TIMER_OFFSET)) + if (vcpu_has_reg(vm, VCPU_ID, KVM_REG_ARM_TIMER_OFFSET) && + !_vcpu_has_device_attr(vm, VCPU_ID, KVM_ARM_VCPU_TIMER_CTRL, + KVM_ARM_VCPU_TIMER_OFFSET)) return; - print_skip("KVM_REG_ARM_TIMER_OFFSET not supported; skipping test"); + print_skip("KVM_REG_ARM_TIMER_OFFSET|KVM_ARM_VCPU_TIMER_OFFSET not supported; skipping test"); exit(KSFT_SKIP); } static void setup_system_counter(struct kvm_vm *vm, struct test_case *test) { + uint64_t cntvoff, cntpoff; struct kvm_one_reg reg = { .id = KVM_REG_ARM_TIMER_OFFSET, - .addr = (__u64)&test->offset, + .addr = (__u64)&cntvoff, }; + if (test->counter == VIRTUAL) { + cntvoff = test->offset; + cntpoff = 0; + } else { + cntvoff = 0; + cntpoff = test->offset; + } + vcpu_set_reg(vm, VCPU_ID, ®); + vcpu_access_device_attr(vm, VCPU_ID, KVM_ARM_VCPU_TIMER_CTRL, + KVM_ARM_VCPU_TIMER_OFFSET, &cntpoff, true); } static uint64_t guest_read_system_counter(struct test_case *test) { switch (test->counter) { case VIRTUAL: + case PHYSICAL_READ_VIRTUAL: return read_cntvct_ordered(); + case PHYSICAL: + return read_cntpct_ordered(); default: GUEST_ASSERT(0); } From patchwork Wed Aug 4 08:58:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Upton X-Patchwork-Id: 12418155 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F420C4338F for ; Wed, 4 Aug 2021 08:59:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4DEB760F6F for ; Wed, 4 Aug 2021 08:59:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236878AbhHDI7T (ORCPT ); Wed, 4 Aug 2021 04:59:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236921AbhHDI7L (ORCPT ); Wed, 4 Aug 2021 04:59:11 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4793C0617A0 for ; Wed, 4 Aug 2021 01:58:58 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id f3-20020a25cf030000b029055a2303fc2dso2245840ybg.11 for ; Wed, 04 Aug 2021 01:58:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=UrN6m22ne+2MDYWmyXjq51ogwq7uHAta0bj5onntA/Q=; b=X4aQIf8yY3OqfJSDV8MlcNYs7slUX/vTpR24OgXx6PSahsoKpv0qisbUa/rdP8tKQY doGothQObaQt5PslknADkm26iL6BfA0QWrR1Mj/mzQ6WzcJyEcJgTs1CizI3TeE8C2Qc ZL7DVu/56+5uybvagLIuXJQEHfHMO7Q+x7dKo+3NotXG6p5YZ7q3+kSsFlShYtAwnCjy eQiB5facl9w8oJAK0Okdq+qDc2gcMUzqP/DhcL/xYm2f1AiWMJWB1n0YVZ1Pm/zfdt3I FHorZUUmFt666pCUyB/NFNmAzWhlF1bNSigEOtoR3kKK4D95DpK11HQcq07BDf8kdicJ 1H3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=UrN6m22ne+2MDYWmyXjq51ogwq7uHAta0bj5onntA/Q=; b=I/qYYsh6u+7ufuP27Gp1Q3P45wusIFumpgOVmZPrMrJt6nI1iG6mpqjSeUS3MQUbSc s94vW1XhAI6H07xmURsGcQAi3hD9SHzC5jHODKRg9eWWM+EE7K0MNvaRdGqca647oFvT MYuNXWc8Gbwkimof5s93IPpT60DL3Svi2ZsP9NzK/w6+HCe4koR5C1OU+skqyScTLDyZ +6Dp+kheC8RX7SK4K07X4FVm3Hwz/9/7HgOF+t7VgvJSNU0mnGwpB+bvCoaBHcTMpihS kh637SEM8Cy3jmX3RJTBIszStJdiviJkZmADZVU//NnG2S3c3uvDFRCXEIOhIbhmQeR1 VIvg== X-Gm-Message-State: AOAM533476QMZZoguRGsO5UCeiZ7Hou7O00UQSecCODsZmwx0GVN4JJQ HOXHSpAXrbY2tFUOSgp0YZtvl8bNkLDImiDAXJsVjcnBbn+EBPhOJfAcrAIg88H0qNnMVz0lDwP tztUJ6VVn1J8UiiAOwUlwxPNuB9unaQbkfPRBmO2xo1IdRsjui+Yo69sDHg== X-Google-Smtp-Source: ABdhPJxFToUuap9PjZfQaJuBYSR+z/ZU9ES4PaTde5JBTP0latCK18tVERJnR8zhdVc33boETZ6k3PUDCPw= X-Received: from oupton.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:404]) (user=oupton job=sendgmr) by 2002:a25:a241:: with SMTP id b59mr33766938ybi.522.1628067537771; Wed, 04 Aug 2021 01:58:57 -0700 (PDT) Date: Wed, 4 Aug 2021 08:58:19 +0000 In-Reply-To: <20210804085819.846610-1-oupton@google.com> Message-Id: <20210804085819.846610-22-oupton@google.com> Mime-Version: 1.0 References: <20210804085819.846610-1-oupton@google.com> X-Mailer: git-send-email 2.32.0.605.g8dce9f2422-goog Subject: [PATCH v6 21/21] selftests: KVM: Add counter emulation benchmark From: Oliver Upton To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini , Sean Christopherson , Marc Zyngier , Peter Shier , Jim Mattson , David Matlack , Ricardo Koller , Jing Zhang , Raghavendra Rao Anata , James Morse , Alexandru Elisei , Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, Andrew Jones , Will Deacon , Catalin Marinas , Oliver Upton Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a test case for counter emulation on arm64. A side effect of how KVM handles physical counter offsetting on non-ECV systems is that the virtual counter will always hit hardware and the physical could be emulated. Force emulation by writing a nonzero offset to the physical counter and compare the elapsed cycles to a direct read of the hardware register. Reviewed-by: Ricardo Koller Signed-off-by: Oliver Upton Reviewed-by: Andrew Jones --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../kvm/aarch64/counter_emulation_benchmark.c | 207 ++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 tools/testing/selftests/kvm/aarch64/counter_emulation_benchmark.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 3d2585f0bffc..a5953f92f6b1 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +/aarch64/counter_emulation_benchmark /aarch64/debug-exceptions /aarch64/get-reg-list /aarch64/vgic_init diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index fab42e7c23ee..d24f7a914992 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -87,6 +87,7 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test +TEST_GEN_PROGS_aarch64 += aarch64/counter_emulation_benchmark TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list TEST_GEN_PROGS_aarch64 += aarch64/vgic_init diff --git a/tools/testing/selftests/kvm/aarch64/counter_emulation_benchmark.c b/tools/testing/selftests/kvm/aarch64/counter_emulation_benchmark.c new file mode 100644 index 000000000000..09ff79ab3d6f --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/counter_emulation_benchmark.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * counter_emulation_benchmark.c -- test to measure the effects of counter + * emulation on guest reads of the physical counter. + * + * Copyright (c) 2021, Google LLC. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" + +#define VCPU_ID 0 + +static struct counter_values { + uint64_t cntvct_start; + uint64_t cntpct; + uint64_t cntvct_end; +} counter_values; + +static uint64_t nr_iterations = 1000; + +static void do_test(void) +{ + /* + * Open-coded approach instead of using helper methods to keep a tight + * interval around the physical counter read. + */ + asm volatile("isb\n\t" + "mrs %[cntvct_start], cntvct_el0\n\t" + "isb\n\t" + "mrs %[cntpct], cntpct_el0\n\t" + "isb\n\t" + "mrs %[cntvct_end], cntvct_el0\n\t" + "isb\n\t" + : [cntvct_start] "=r"(counter_values.cntvct_start), + [cntpct] "=r"(counter_values.cntpct), + [cntvct_end] "=r"(counter_values.cntvct_end)); +} + +static void guest_main(void) +{ + int i; + + for (i = 0; i < nr_iterations; i++) { + do_test(); + GUEST_SYNC(i); + } + + for (i = 0; i < nr_iterations; i++) { + do_test(); + GUEST_SYNC(i); + } +} + +static void enter_guest(struct kvm_vm *vm) +{ + struct ucall uc; + + vcpu_ioctl(vm, VCPU_ID, KVM_RUN, NULL); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_SYNC: + break; + case UCALL_ABORT: + TEST_ASSERT(false, "%s at %s:%ld", (const char *)uc.args[0], + __FILE__, uc.args[1]); + break; + default: + TEST_ASSERT(false, "unexpected exit: %s", + exit_reason_str(vcpu_state(vm, VCPU_ID)->exit_reason)); + break; + } +} + +static double counter_frequency(void) +{ + uint32_t freq; + + asm volatile("mrs %0, cntfrq_el0" + : "=r" (freq)); + + return freq / 1000000.0; +} + +static void log_csv(FILE *csv, bool trapped) +{ + double freq = counter_frequency(); + + fprintf(csv, "%s,%.02f,%lu,%lu,%lu\n", + trapped ? "true" : "false", freq, + counter_values.cntvct_start, + counter_values.cntpct, + counter_values.cntvct_end); +} + +static double run_loop(struct kvm_vm *vm, FILE *csv, bool trapped) +{ + double avg = 0; + int i; + + for (i = 0; i < nr_iterations; i++) { + uint64_t delta; + + enter_guest(vm); + sync_global_from_guest(vm, counter_values); + + if (csv) + log_csv(csv, trapped); + + delta = counter_values.cntvct_end - counter_values.cntvct_start; + avg = ((avg * i) + delta) / (i + 1); + } + + return avg; +} + +static void setup_counter(struct kvm_vm *vm, uint64_t offset) +{ + vcpu_access_device_attr(vm, VCPU_ID, KVM_ARM_VCPU_TIMER_CTRL, + KVM_ARM_VCPU_TIMER_OFFSET, &offset, + true); +} + +static void run_tests(struct kvm_vm *vm, FILE *csv) +{ + double avg_trapped, avg_native, freq; + + freq = counter_frequency(); + + if (csv) + fputs("trapped,freq_mhz,cntvct_start,cntpct,cntvct_end\n", csv); + + /* no physical offsetting; kvm allows reads of cntpct_el0 */ + setup_counter(vm, 0); + avg_native = run_loop(vm, csv, false); + + /* force emulation of the physical counter */ + setup_counter(vm, 1); + avg_trapped = run_loop(vm, csv, true); + + pr_info("%lu iterations: average cycles (@%.02fMHz) native: %.02f, trapped: %.02f\n", + nr_iterations, freq, avg_native, avg_trapped); +} + +static void usage(const char *program_name) +{ + fprintf(stderr, + "Usage: %s [-h] [-o csv_file] [-n iterations]\n" + " -h prints this message\n" + " -n number of test iterations (default: %lu)\n" + " -o csv file to write data\n", + program_name, nr_iterations); +} + +int main(int argc, char **argv) +{ + struct kvm_vm *vm; + FILE *csv = NULL; + int opt; + + while ((opt = getopt(argc, argv, "hn:o:")) != -1) { + switch (opt) { + case 'o': + csv = fopen(optarg, "w"); + if (!csv) { + fprintf(stderr, "failed to open file '%s': %d\n", + optarg, errno); + exit(1); + } + break; + case 'n': + nr_iterations = strtoul(optarg, NULL, 0); + break; + default: + fprintf(stderr, "unrecognized option: '-%c'\n", opt); + /* fallthrough */ + case 'h': + usage(argv[0]); + exit(1); + } + } + + vm = vm_create_default(VCPU_ID, 0, guest_main); + sync_global_to_guest(vm, nr_iterations); + ucall_init(vm, NULL); + + if (_vcpu_has_device_attr(vm, VCPU_ID, KVM_ARM_VCPU_TIMER_CTRL, + KVM_ARM_VCPU_TIMER_OFFSET)) { + print_skip("KVM_ARM_VCPU_TIMER_OFFSET not supported."); + exit(KSFT_SKIP); + } + + run_tests(vm, csv); + kvm_vm_free(vm); + + if (csv) + fclose(csv); +}