From patchwork Wed Feb 17 12:35:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Fleming X-Patchwork-Id: 62108 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp2258549lbl; Wed, 17 Feb 2016 04:39:49 -0800 (PST) X-Received: by 10.98.76.194 with SMTP id e63mr1776271pfj.9.1455712789682; Wed, 17 Feb 2016 04:39:49 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tf4si1677833pab.231.2016.02.17.04.39.48; Wed, 17 Feb 2016 04:39:49 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dkim=pass header.i=@codeblueprint-co-uk.20150623.gappssmtp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1422834AbcBQMjq (ORCPT + 30 others); Wed, 17 Feb 2016 07:39:46 -0500 Received: from mail-wm0-f44.google.com ([74.125.82.44]:38671 "EHLO mail-wm0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965076AbcBQMgM (ORCPT ); Wed, 17 Feb 2016 07:36:12 -0500 Received: by mail-wm0-f44.google.com with SMTP id a4so25956022wme.1 for ; Wed, 17 Feb 2016 04:36:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=codeblueprint-co-uk.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Fp8LRQ/UMf12ZOBn9f4fLBgxPoTFB/HhRXnuFBFy6W4=; b=WyWqqMsNWKqxJKrbjWsD9VtQyearjQTafn1Xw+wb5FJ564cVOJr5LLWEpmzO00OfFm L4dxiyJal99jMIkD1L2zOMhoqsO7VfDSs154CQg5RDrhk8ScgRehjpwOAHaICSDYMGQT lisR50IXY6GCqlYBtRdXeRq7AZT/uD/aL5WUSn5S9W6zfdfbQ+msyzgH7nR1iUNgBHds uNfkRgimooVFLNyn9WijSm1iNgpOH8PTWn0z0MO2ohL4HYWWWl/tFxLaW8Q8z/WhaUvN LwWkEVI1HWaavf6G5m4YCoFIMHQGG6slt1HeF4wmY2cPmjPorqAsdRYdlfF/wGK3IAJh K8gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Fp8LRQ/UMf12ZOBn9f4fLBgxPoTFB/HhRXnuFBFy6W4=; b=i+84KXAxLihYU2xHpwK2frRSSUZXybjbhgR/ytvgkFkKyImOFjNOBg0LNQ/KhCNRDJ wKCVSAw8loMvsFB6eUV450ZlxM3nG5/LLsZwQU6e6ODem8q8YeUwqezMWJPSvb9hSSnF 3PpqMi4I63FlYEVWmcZLLrEuZv0rUXRqezc/nnjkEbOsqEBLc58dRTxbHC3e5ctVgTpT ja0mI+KtzYE/ySNBgr/t5SWbzGUUtNppjMpVWszHf5Me4wjRcAoswg3IswhGZx81AZKU WAX3pG0GiGw697A6cLNWdYDOHEMpXCQZdd3W2hr4TF6g0aIy5S/kkILrtqM9fGemq88i WZOw== X-Gm-Message-State: AG10YOQfdkCAHHoj1sbvL1ibmjpEmErEawXJqTGU2ADy0F7Qf5zHwxXWFemJJCrJsEZhHg== X-Received: by 10.194.77.35 with SMTP id p3mr1589163wjw.91.1455712571511; Wed, 17 Feb 2016 04:36:11 -0800 (PST) Received: from localhost (5ec16434.skybroadband.com. [94.193.100.52]) by smtp.gmail.com with ESMTPSA id n9sm1293436wjy.36.2016.02.17.04.36.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 17 Feb 2016 04:36:10 -0800 (PST) From: Matt Fleming To: Ingo Molnar , Thomas Gleixner , "H . Peter Anvin" Cc: Ard Biesheuvel , linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, Andy Lutomirski , Linus Torvalds , Sai Praneeth Prakhya , Peter Zijlstra , Matt Fleming Subject: [PATCH 02/13] efi/runtime-wrappers: Run UEFI Runtime Services with interrupts enabled Date: Wed, 17 Feb 2016 12:35:55 +0000 Message-Id: <1455712566-16727-3-git-send-email-matt@codeblueprint.co.uk> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1455712566-16727-1-git-send-email-matt@codeblueprint.co.uk> References: <1455712566-16727-1-git-send-email-matt@codeblueprint.co.uk> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ard Biesheuvel The UEFI spec allows Runtime Services to be invoked with interrupts enabled. The only reason we were disabling interrupts was to prevent recursive calls into the services on the same CPU, which will lead to deadlock. However, the only context where such invocations may occur legally is from efi-pstore via efivars, and that code has been updated to call a non-blocking alternative when invoked from a non-interruptible context. So instead, update the ordinary, blocking UEFI Runtime Services wrappers to execute with interrupts enabled. This aims to prevent excessive interrupt latencies on uniprocessor platforms with slow variable stores. Note that other OSes such as Windows call UEFI Runtime Services with interrupts enabled as well. Signed-off-by: Ard Biesheuvel Cc: Andy Lutomirski Cc: Linus Torvalds Cc: Sai Praneeth Prakhya Cc: Peter Zijlstra Signed-off-by: Matt Fleming --- drivers/firmware/efi/runtime-wrappers.c | 71 +++++++++++++-------------------- 1 file changed, 28 insertions(+), 43 deletions(-) -- 2.6.2 diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 7b8b2f2702ca..de6953039af6 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -63,23 +63,21 @@ static DEFINE_SPINLOCK(efi_runtime_lock); static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(get_time, tm, tc); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } static efi_status_t virt_efi_set_time(efi_time_t *tm) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(set_time, tm); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -87,23 +85,21 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(get_wakeup_time, enabled, pending, tm); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(set_wakeup_time, enabled, tm); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -113,13 +109,12 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name, unsigned long *data_size, void *data) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(get_variable, name, vendor, attr, data_size, data); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -127,12 +122,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(get_next_variable, name_size, name, vendor); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -142,13 +136,12 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, unsigned long data_size, void *data) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(set_variable, name, vendor, attr, data_size, data); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -157,15 +150,14 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, u32 attr, unsigned long data_size, void *data) { - unsigned long flags; efi_status_t status; - if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) + if (!spin_trylock(&efi_runtime_lock)) return EFI_NOT_READY; status = efi_call_virt(set_variable, name, vendor, attr, data_size, data); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -175,16 +167,15 @@ static efi_status_t virt_efi_query_variable_info(u32 attr, u64 *remaining_space, u64 *max_variable_size) { - unsigned long flags; efi_status_t status; if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(query_variable_info, attr, storage_space, remaining_space, max_variable_size); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -194,29 +185,27 @@ virt_efi_query_variable_info_nonblocking(u32 attr, u64 *remaining_space, u64 *max_variable_size) { - unsigned long flags; efi_status_t status; if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; - if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) + if (!spin_trylock(&efi_runtime_lock)) return EFI_NOT_READY; status = efi_call_virt(query_variable_info, attr, storage_space, remaining_space, max_variable_size); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) { - unsigned long flags; efi_status_t status; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(get_next_high_mono_count, count); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -225,26 +214,23 @@ static void virt_efi_reset_system(int reset_type, unsigned long data_size, efi_char16_t *data) { - unsigned long flags; - - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); __efi_call_virt(reset_system, reset_type, status, data_size, data); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); } static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, unsigned long count, unsigned long sg_list) { - unsigned long flags; efi_status_t status; if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(update_capsule, capsules, count, sg_list); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; } @@ -253,16 +239,15 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, u64 *max_size, int *reset_type) { - unsigned long flags; efi_status_t status; if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; - spin_lock_irqsave(&efi_runtime_lock, flags); + spin_lock(&efi_runtime_lock); status = efi_call_virt(query_capsule_caps, capsules, count, max_size, reset_type); - spin_unlock_irqrestore(&efi_runtime_lock, flags); + spin_unlock(&efi_runtime_lock); return status; }