From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752236AbdBFVC6 (ORCPT ); Mon, 6 Feb 2017 16:02:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52140 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750995AbdBFVC5 (ORCPT ); Mon, 6 Feb 2017 16:02:57 -0500 From: Waiman Long To: Jeremy Fitzhardinge , Chris Wright , Alok Kataria , Rusty Russell , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" Cc: x86@kernel.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Waiman Long Subject: [PATCH] x86/paravirt: Avoid setting IF flag, if not necessary Date: Mon, 6 Feb 2017 16:02:41 -0500 Message-Id: <1486414961-1065-1-git-send-email-longman@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 06 Feb 2017 21:02:57 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Setting the IF flag can cause an VM exit. So we should avoid touching the IF flag until absolutely necessary. This patch change the way the paravirt arch_local_irq_restore() works by checking the previous flags value and call arch_local_irq_enable() only if the IF flag was set previously. On a 32 vCPUs KVM guest running the AIM7 five-sec workload, the performance increased slightly from 302136.32 jobs/min to 306185.57 (about 1.3%) jobs/min and the %CPU time consumed by _raw_spin_unlock_irqrestore decreased slightly from 1.68% to 1.53% with this patch. Signed-off-by: Waiman Long --- arch/x86/include/asm/paravirt.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 1eea6ca..864f57b 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -6,6 +6,7 @@ #ifdef CONFIG_PARAVIRT #include #include +#include #include @@ -762,11 +763,6 @@ static inline notrace unsigned long arch_local_save_flags(void) return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl); } -static inline notrace void arch_local_irq_restore(unsigned long f) -{ - PVOP_VCALLEE1(pv_irq_ops.restore_fl, f); -} - static inline notrace void arch_local_irq_disable(void) { PVOP_VCALLEE0(pv_irq_ops.irq_disable); @@ -786,6 +782,16 @@ static inline notrace unsigned long arch_local_irq_save(void) return f; } +/* + * In a VM, setting the IF flag can cause an expensive VM exit. So if + * interrupt was disabled before arch_local_irq_save(), we don't need to + * do anything at all, thus saving an VM exit. + */ +static inline notrace void arch_local_irq_restore(unsigned long f) +{ + if (f & X86_EFLAGS_IF) + arch_local_irq_enable(); +} /* Make sure as little as possible of this mess escapes. */ #undef PARAVIRT_CALL -- 1.8.3.1