From patchwork Fri May 12 01:12:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wanpeng Li X-Patchwork-Id: 9723377 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6D678600CB for ; Fri, 12 May 2017 01:12:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63CE728579 for ; Fri, 12 May 2017 01:12:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 58860285FB; Fri, 12 May 2017 01:12:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0DEA328579 for ; Fri, 12 May 2017 01:12:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757412AbdELBMM (ORCPT ); Thu, 11 May 2017 21:12:12 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:33531 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755615AbdELBMJ (ORCPT ); Thu, 11 May 2017 21:12:09 -0400 Received: by mail-pg0-f65.google.com with SMTP id s62so5536656pgc.0; Thu, 11 May 2017 18:12:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=v1CG0tAqcPBkVb8SA8vaAdPtrw+xqeOIe31/9/bW1CI=; b=p+LuwylgRiL7X1P1c/1d3dEXoNX/1eFXv48JHGU7WSBVRHtfe7rx9n5TmAPLMwgdqB YYOzest4rFE9Ktcu2wFnC/BtsIcyJll4+iLTtzI0RxMUXAE81TlOvVlYzYD8Au4QxJEm ydknC2AC2y38VmUhB8nOWxMmxEL9xrMyuvukaoJGF+1IorIm7obiK6QeF+M349IbGhTE XkOBArJejTL+lkH/vxOWQXwj+fvITCnIwajkEQ66rEYQmkBF348q9zcLLWnNlVje52xY z0fwaIJ11M2ah9vVANWSdWF+Lg01r6JCyJlbDAYNJ9XrsgHD9ES+8PvS5cCP1pm3eu+B trfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=v1CG0tAqcPBkVb8SA8vaAdPtrw+xqeOIe31/9/bW1CI=; b=rvH0EDZvpBL396ou2agQhdTY+roHqsSNPmfETxLBnGWRyXJpA48GAphEHSSuYBsvny CCYUTDVN0Fy6YWvUL1b7aezaZuWRnCQcUTK3fQ3cC7VG5FSvuh5a2lEdcNs6HaAazcud CcCCeWI1s6wNzq+iAaN8TzzXJqxy12kML9DT23oksyulFmgh/GPlDdBcGxuZ1D9LeifE hPDG2jpmRYgM7PQlXhDePIgOfHVaqoX0vI6ib0IzAMZb8i3yLl4kbAmE86hnTVv+Gdfq NOuYhc1kidaez/tJ0r0V6WX9Riw3DWhAUE1LAI093QlJbQMg90wfj56TRqWl4SN2Yu8K TO7A== X-Gm-Message-State: AODbwcAb7QYGOK0hTErnyp2gpekDaYJCq8kvQi7z97oKSlFGkrfeaNS3 EIYdlvZ6ZD3jQQ== X-Received: by 10.99.142.73 with SMTP id k70mr1577446pge.0.1494551528254; Thu, 11 May 2017 18:12:08 -0700 (PDT) Received: from localhost ([203.205.141.123]) by smtp.gmail.com with ESMTPSA id o5sm2090370pga.64.2017.05.11.18.12.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 May 2017 18:12:07 -0700 (PDT) From: Wanpeng Li X-Google-Original-From: Wanpeng Li To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Wanpeng Li Subject: [PATCH v3] KVM: x86: Fix potential preemption when get the current kvmclock timestamp Date: Thu, 11 May 2017 18:12:05 -0700 Message-Id: <1494551525-4100-1-git-send-email-wanpeng.li@hotmail.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Wanpeng Li BUG: using __this_cpu_read() in preemptible [00000000] code: qemu-system-x86/2809 caller is __this_cpu_preempt_check+0x13/0x20 CPU: 2 PID: 2809 Comm: qemu-system-x86 Not tainted 4.11.0+ #13 Call Trace: dump_stack+0x99/0xce check_preemption_disabled+0xf5/0x100 __this_cpu_preempt_check+0x13/0x20 get_kvmclock_ns+0x6f/0x110 [kvm] get_time_ref_counter+0x5d/0x80 [kvm] kvm_hv_process_stimers+0x2a1/0x8a0 [kvm] ? kvm_hv_process_stimers+0x2a1/0x8a0 [kvm] ? kvm_arch_vcpu_ioctl_run+0xac9/0x1ce0 [kvm] kvm_arch_vcpu_ioctl_run+0x5bf/0x1ce0 [kvm] kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? __fget+0xf3/0x210 do_vfs_ioctl+0xa4/0x700 ? __fget+0x114/0x210 SyS_ioctl+0x79/0x90 entry_SYSCALL_64_fastpath+0x23/0xc2 RIP: 0033:0x7f9d164ed357 ? __this_cpu_preempt_check+0x13/0x20 This can be reproduced by run kvm-unit-tests/hyperv_stimer.flat w/ CONFIG_PREEMPT and CONFIG_DEBUG_PREEMPT enabled. Safe access to per-CPU data requires a couple of constraints, though: the thread working with the data cannot be preempted and it cannot be migrated while it manipulates per-CPU variables. If the thread is preempted, the thread that replaces it could try to work with the same variables; migration to another CPU could also cause confusion. However there is no preemption disable when reads host per-CPU tsc rate to calculate the current kvmclock timestamp. This patch fixes it by utilizing get_cpu/put_cpu pair to guarantee both __this_cpu_read() and rdtsc() are not preempted. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Reviewed-by: Paolo Bonzini --- v2 -> v3: * update patch description v1 -> v2: * utilize get_cpu/put_cpu pair to protect both __this_cpu_read and rdtsc() arch/x86/kvm/x86.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b54125b..3b5fc7e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1763,6 +1763,7 @@ u64 get_kvmclock_ns(struct kvm *kvm) { struct kvm_arch *ka = &kvm->arch; struct pvclock_vcpu_time_info hv_clock; + u64 ret; spin_lock(&ka->pvclock_gtod_sync_lock); if (!ka->use_master_clock) { @@ -1774,10 +1775,17 @@ u64 get_kvmclock_ns(struct kvm *kvm) hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; spin_unlock(&ka->pvclock_gtod_sync_lock); + /* both __this_cpu_read() and rdtsc() should be on the same cpu */ + get_cpu(); + kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, &hv_clock.tsc_shift, &hv_clock.tsc_to_system_mul); - return __pvclock_read_cycles(&hv_clock, rdtsc()); + ret = __pvclock_read_cycles(&hv_clock, rdtsc()); + + put_cpu(); + + return ret; } static void kvm_setup_pvclock_page(struct kvm_vcpu *v)