From patchwork Mon Feb 1 22:07:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Fleming X-Patchwork-Id: 60972 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp350082lbb; Mon, 1 Feb 2016 14:07:36 -0800 (PST) X-Received: by 10.66.236.69 with SMTP id us5mr42239057pac.93.1454364456831; Mon, 01 Feb 2016 14:07:36 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id wg10si26634431pac.23.2016.02.01.14.07.36; Mon, 01 Feb 2016 14:07:36 -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 S932826AbcBAWHb (ORCPT + 30 others); Mon, 1 Feb 2016 17:07:31 -0500 Received: from mail-wm0-f54.google.com ([74.125.82.54]:36726 "EHLO mail-wm0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932701AbcBAWHZ (ORCPT ); Mon, 1 Feb 2016 17:07:25 -0500 Received: by mail-wm0-f54.google.com with SMTP id p63so91646935wmp.1 for ; Mon, 01 Feb 2016 14:07:24 -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=kXQUUvwRxoUXEHhhFEjYGhV1Tg7b+WAshsBzZ/66mdg=; b=u3oBx10qzxLZW50eEE8s8jcBxxqa57DmaS6Np+ulY3YHjdKtY3hJpytIyLZqqDiM/a M8+3Upl4+ms2xFJhN2wV39htR+TW8s/15X2nr3LLyfiYgPTkz97GeHCTO/HkEN+uSyg4 wCF/vox6M8/1tTaZngEIly13qYiNw+/k9Qn65PxDS7okLtSzVQ/5kiBG8noRAhvTxPcW ZGoHZmGGfciYMj9ZHDQYaNJHdJ7dPyQD/FCuGU/ysTEqGc90/Y4ylB4QmFoQOiJY5oXH JKcEzxuLu3Wuzf1pAG14UDN9KX4gtZAAWfBjbmiVupC79oUXy1/MESjFkDrKgpd2kSqx FZlg== 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=kXQUUvwRxoUXEHhhFEjYGhV1Tg7b+WAshsBzZ/66mdg=; b=SQIpI401sahV/eWGQ2aWRJpxNfnmLlbKpG9xBOa3ePx3hy/819VUAtOydSVD5evK9o C4/+TqzG8Y2MjoezqMdI/sKH4UxdRMrUTAOcdbP/+K3ICAqu5JMqOnEkKwqBLsDq57Ss kFHfVK4Wt0hqFSzgdrDyM6BrC0zU58SmufEtKzxMGOL2aRYz/PPPVMJh7qAutgRu51dm AMYVjSg2L7PJMyi0KaicJH3XsDzVVkEN4sGxEmR1mX7O7B2Cbl7nYCMFIMidu8TPg+TU Q0C/VzQY+KQxtLSdq0EE5fYyHKzVMLswdTiC77Ows1Pv5/ceSO/sri7z4i41/8cKJlM5 qrGw== X-Gm-Message-State: AG10YORYo8O/zacDOATjWzRk2cPdC9j/C31qH/ojIZL4fNlfjzUkOid+9OeZpR3f8NleAQ== X-Received: by 10.28.126.205 with SMTP id z196mr13459689wmc.44.1454364443657; Mon, 01 Feb 2016 14:07:23 -0800 (PST) Received: from localhost (5ec16434.skybroadband.com. [94.193.100.52]) by smtp.gmail.com with ESMTPSA id g3sm31134381wjw.31.2016.02.01.14.07.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 01 Feb 2016 14:07:22 -0800 (PST) From: Matt Fleming To: Ingo Molnar , "H . Peter Anvin" , Thomas Gleixner Cc: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, Ard Biesheuvel , Matt Fleming Subject: [PATCH 07/14] efi: runtime-wrappers: Run UEFI Runtime Services with interrupts enabled Date: Mon, 1 Feb 2016 22:07:01 +0000 Message-Id: <1454364428-494-8-git-send-email-matt@codeblueprint.co.uk> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1454364428-494-1-git-send-email-matt@codeblueprint.co.uk> References: <1454364428-494-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. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming --- drivers/firmware/efi/runtime-wrappers.c | 73 ++++++++++++++------------------- 1 file changed, 30 insertions(+), 43 deletions(-) -- 2.6.2 diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 7b8b2f2702ca..aa3d9d0a27e6 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,13 @@ 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); + BUG_ON(in_irq()); + + 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 +138,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 +152,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 +169,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 +187,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 +216,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 +241,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; }