public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86, efi: retry ExitBootServices() on failure
@ 2013-06-11  6:52 Matt Fleming
  2013-06-11  7:22 ` Matt Fleming
  2013-06-13 16:00 ` joeyli
  0 siblings, 2 replies; 19+ messages in thread
From: Matt Fleming @ 2013-06-11  6:52 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-kernel, Matthew Garrett, Zach Bobroff, stable, Matt Fleming

From: Zach Bobroff <zacharyb@ami.com>

ExitBootServices is absolutely supposed to return a failure if any
ExitBootServices event handler changes the memory map.  Basically the
get_map loop should run again if ExitBootServices returns an error the
first time.  I would say it would be fair that if ExitBootServices gives
an error the second time then Linux would be fine in returning control
back to BIOS.

The second change is the following line:

again:
        size += sizeof(*mem_map) * 2;

Originally you were incrementing it by the size of one memory map entry.
The issue here is all related to the low_alloc routine you are using.
In this routine you are making allocations to get the memory map itself.
Doing this allocation or allocations can affect the memory map by more
than one record.

[ mfleming - changelog, code style ]
Signed-off-by: Zach Bobroff <zacharyb@ami.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
 arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 35ee62f..7c6e5d9 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1037,18 +1037,20 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
 	efi_memory_desc_t *mem_map;
 	efi_status_t status;
 	__u32 desc_version;
+	bool called_exit = false;
 	u8 nr_entries;
 	int i;
 
 	size = sizeof(*mem_map) * 32;
 
 again:
-	size += sizeof(*mem_map);
+	size += sizeof(*mem_map) * 2;
 	_size = size;
 	status = low_alloc(size, 1, (unsigned long *)&mem_map);
 	if (status != EFI_SUCCESS)
 		return status;
 
+get_map:
 	status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
 				mem_map, &key, &desc_size, &desc_version);
 	if (status == EFI_BUFFER_TOO_SMALL) {
@@ -1074,8 +1076,20 @@ again:
 	/* Might as well exit boot services now */
 	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
 				handle, key);
-	if (status != EFI_SUCCESS)
-		goto free_mem_map;
+	if (status != EFI_SUCCESS) {
+		/*
+		 * ExitBootServices() will fail if any of the event
+		 * handlers change the memory map. In which case, we
+		 * must be prepared to retry, but only once so that
+		 * we're guaranteed to exit on repeated failures instead
+		 * of spinning forever.
+		 */
+		if (called_exit)
+			goto free_mem_map;
+
+		called_exit = true;
+		goto get_map;
+	}
 
 	/* Historic? */
 	boot_params->alt_mem_k = 32 * 1024;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2013-06-26 13:12 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-11  6:52 [PATCH] x86, efi: retry ExitBootServices() on failure Matt Fleming
2013-06-11  7:22 ` Matt Fleming
2013-06-13 16:00 ` joeyli
2013-06-17  9:21   ` Matt Fleming
2013-06-17  9:46     ` Jan Beulich
2013-06-17 10:17       ` Matt Fleming
2013-06-17 10:41         ` joeyli
2013-06-17 11:02         ` Jan Beulich
2013-06-17 12:30           ` Matt Fleming
2013-06-18  0:18             ` Zachary Bobroff
2013-06-18  2:47               ` joeyli
2013-06-18  4:20                 ` Zachary Bobroff
2013-06-18  7:34                   ` joeyli
2013-06-18 13:03               ` Jan Beulich
2013-06-18 22:12                 ` Zachary Bobroff
2013-06-19  8:43                   ` matt
2013-06-19  8:53                     ` H. Peter Anvin
2013-06-20 18:04                       ` Zachary Bobroff
2013-06-26 13:12                         ` matt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox