Re: [PATCHv3] x86: EFI stub support for large memory maps
On Fri, 27 Sep, at 05:46:07PM, Linn Crosetto wrote: > Given that we have already successfully called exit_boot_services, can > we still make this call to free_pool? Urgh, good point. The answer is "no, not really". I'll add your change verbatim and push out the 'next' branch again. -- Matt Fleming, Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv3] x86: EFI stub support for large memory maps
On Thu, Sep 26, 2013 at 12:34:00PM +0100, Matt Fleming wrote: > > I might add the following to your merge for semantic reasons: > > > > diff --git a/arch/x86/boot/compressed/eboot.c > > b/arch/x86/boot/compressed/eboot.c > > index 04b228d..a7677ba 100644 > > --- a/arch/x86/boot/compressed/eboot.c > > +++ b/arch/x86/boot/compressed/eboot.c > > @@ -730,6 +730,8 @@ get_map: > > boot_params->alt_mem_k = 32 * 1024; > > > > status = setup_e820(boot_params, e820ext, e820ext_size); > > + if (status != EFI_SUCCESS) > > + return status; > > > > return EFI_SUCCESS; > > Aha, nice catch! Though if setup_e820() fails we should be jumping to > the 'free_mem_map' label so we don't leak the memory map, like so, > > diff --git a/arch/x86/boot/compressed/eboot.c > b/arch/x86/boot/compressed/eboot.c > index 04b228d..602950b 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -730,8 +730,8 @@ get_map: > boot_params->alt_mem_k = 32 * 1024; > > status = setup_e820(boot_params, e820ext, e820ext_size); > - > - return EFI_SUCCESS; > + if (status == EFI_SUCCESS) > + return status; > > free_mem_map: > efi_call_phys1(sys_table->boottime->free_pool, mem_map); Given that we have already successfully called exit_boot_services, can we still make this call to free_pool? -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv3] x86: EFI stub support for large memory maps
On Wed, 25 Sep, at 04:45:41PM, Linn Crosetto wrote: > On Wed, Sep 25, 2013 at 01:58:40PM +0100, Matt Fleming wrote: > > On Sun, 22 Sep, at 07:59:08PM, Linn Crosetto wrote: > > > This patch fixes a problem with EFI memory maps larger than 128 entries > > > when booting using the EFI stub, which results in overflowing e820_map > > > in boot_params and an eventual halt when checking the map size in > > > sanitize_e820_map(). > > > > > > If the number of map entries is greater than what can fit in e820_map, > > > add the extra entries to the setup_data list using type SETUP_E820_EXT. > > > These extra entries are then picked up when the setup_data list is > > > parsed in parse_e820_ext(). > > > > > > Signed-off-by: Linn Crosetto > > > --- > > > Changes from v2: > > > * Removed unnecessary optimization in alloc_e820ext() (Matt Fleming) > > > * Fixed a bug where an incorrect buffer size may be passed to > > >get_memory_map when jumping to get_map > > > > > > arch/x86/boot/compressed/eboot.c | 239 > > > +++ > > > 1 file changed, 167 insertions(+), 72 deletions(-) > > > > Thanks Linn. I applied this to the 'next' branch at, > > > > git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git > > > > but it required a bit of massaging to apply on top of the changes > > already there. Could you confirm that my changes are OK? I've included > > the modified commit below. > > I have tested the 'next' branch on a system with a large number of entries in > the memory map and the merge appears to be functionally correct. Excellent, thank you for verifying. > With the change in commit ae8e9060, I noticed the memory map is no longer > placed > in memory allocated with low_alloc(). I have not looked into what effect it > could have, if any. Correct. I haven't run into any problems on my test machines. > > + /* Historic? */ > > + boot_params->alt_mem_k = 32 * 1024; > > + > > + status = setup_e820(boot_params, e820ext, e820ext_size); > > > > return EFI_SUCCESS; > > I might add the following to your merge for semantic reasons: > > diff --git a/arch/x86/boot/compressed/eboot.c > b/arch/x86/boot/compressed/eboot.c > index 04b228d..a7677ba 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -730,6 +730,8 @@ get_map: > boot_params->alt_mem_k = 32 * 1024; > > status = setup_e820(boot_params, e820ext, e820ext_size); > + if (status != EFI_SUCCESS) > + return status; > > return EFI_SUCCESS; Aha, nice catch! Though if setup_e820() fails we should be jumping to the 'free_mem_map' label so we don't leak the memory map, like so, diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 04b228d..602950b 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -730,8 +730,8 @@ get_map: boot_params->alt_mem_k = 32 * 1024; status = setup_e820(boot_params, e820ext, e820ext_size); - - return EFI_SUCCESS; + if (status == EFI_SUCCESS) + return status; free_mem_map: efi_call_phys1(sys_table->boottime->free_pool, mem_map); I've fixed this up and pushed out a new patch. -- Matt Fleming, Intel Open Source Technology Center -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv3] x86: EFI stub support for large memory maps
On Wed, Sep 25, 2013 at 01:58:40PM +0100, Matt Fleming wrote: > On Sun, 22 Sep, at 07:59:08PM, Linn Crosetto wrote: > > This patch fixes a problem with EFI memory maps larger than 128 entries > > when booting using the EFI stub, which results in overflowing e820_map > > in boot_params and an eventual halt when checking the map size in > > sanitize_e820_map(). > > > > If the number of map entries is greater than what can fit in e820_map, > > add the extra entries to the setup_data list using type SETUP_E820_EXT. > > These extra entries are then picked up when the setup_data list is > > parsed in parse_e820_ext(). > > > > Signed-off-by: Linn Crosetto > > --- > > Changes from v2: > > * Removed unnecessary optimization in alloc_e820ext() (Matt Fleming) > > * Fixed a bug where an incorrect buffer size may be passed to > >get_memory_map when jumping to get_map > > > > arch/x86/boot/compressed/eboot.c | 239 > > +++ > > 1 file changed, 167 insertions(+), 72 deletions(-) > > Thanks Linn. I applied this to the 'next' branch at, > > git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git > > but it required a bit of massaging to apply on top of the changes > already there. Could you confirm that my changes are OK? I've included > the modified commit below. I have tested the 'next' branch on a system with a large number of entries in the memory map and the merge appears to be functionally correct. With the change in commit ae8e9060, I noticed the memory map is no longer placed in memory allocated with low_alloc(). I have not looked into what effect it could have, if any. > + /* Historic? */ > + boot_params->alt_mem_k = 32 * 1024; > + > + status = setup_e820(boot_params, e820ext, e820ext_size); > > return EFI_SUCCESS; I might add the following to your merge for semantic reasons: diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 04b228d..a7677ba 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -730,6 +730,8 @@ get_map: boot_params->alt_mem_k = 32 * 1024; status = setup_e820(boot_params, e820ext, e820ext_size); + if (status != EFI_SUCCESS) + return status; return EFI_SUCCESS; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv3] x86: EFI stub support for large memory maps
On Sun, 22 Sep, at 07:59:08PM, Linn Crosetto wrote: > This patch fixes a problem with EFI memory maps larger than 128 entries > when booting using the EFI stub, which results in overflowing e820_map > in boot_params and an eventual halt when checking the map size in > sanitize_e820_map(). > > If the number of map entries is greater than what can fit in e820_map, > add the extra entries to the setup_data list using type SETUP_E820_EXT. > These extra entries are then picked up when the setup_data list is > parsed in parse_e820_ext(). > > Signed-off-by: Linn Crosetto > --- > Changes from v2: > * Removed unnecessary optimization in alloc_e820ext() (Matt Fleming) > * Fixed a bug where an incorrect buffer size may be passed to >get_memory_map when jumping to get_map > > arch/x86/boot/compressed/eboot.c | 239 > +++ > 1 file changed, 167 insertions(+), 72 deletions(-) Thanks Linn. I applied this to the 'next' branch at, git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git but it required a bit of massaging to apply on top of the changes already there. Could you confirm that my changes are OK? I've included the modified commit below. --- >From 81c9e1df196ad531edabe726a2d7a610fb04fdd6 Mon Sep 17 00:00:00 2001 From: Linn Crosetto Date: Sun, 22 Sep 2013 19:59:08 -0600 Subject: [PATCH] x86: EFI stub support for large memory maps This patch fixes a problem with EFI memory maps larger than 128 entries when booting using the EFI stub, which results in overflowing e820_map in boot_params and an eventual halt when checking the map size in sanitize_e820_map(). If the number of map entries is greater than what can fit in e820_map, add the extra entries to the setup_data list using type SETUP_E820_EXT. These extra entries are then picked up when the setup_data list is parsed in parse_e820_ext(). Signed-off-by: Linn Crosetto Signed-off-by: Matt Fleming --- arch/x86/boot/compressed/eboot.c | 220 --- 1 file changed, 159 insertions(+), 61 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index beb07a4..482006e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -519,71 +519,47 @@ fail: return NULL; } -static efi_status_t exit_boot(struct boot_params *boot_params, - void *handle) +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) { - struct efi_info *efi = &boot_params->efi_info; - struct e820entry *e820_map = &boot_params->e820_map[0]; - struct e820entry *prev = NULL; - unsigned long size, key, desc_size, _size; - efi_memory_desc_t *mem_map; + struct setup_data *data; efi_status_t status; - __u32 desc_version; - bool called_exit = false; - u8 nr_entries; - int i; + unsigned long size; -get_map: - status = efi_get_memory_map(sys_table, &mem_map, &size, &desc_size, - &desc_version, &key); + e820ext->type = SETUP_E820_EXT; + e820ext->len = nr_entries * sizeof(struct e820entry); + e820ext->next = 0; - if (status != EFI_SUCCESS) - return status; - - memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); - efi->efi_systab = (unsigned long)sys_table; - efi->efi_memdesc_size = desc_size; - efi->efi_memdesc_version = desc_version; - efi->efi_memmap = (unsigned long)mem_map; - efi->efi_memmap_size = size; - -#ifdef CONFIG_X86_64 - efi->efi_systab_hi = (unsigned long)sys_table >> 32; - efi->efi_memmap_hi = (unsigned long)mem_map >> 32; -#endif + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; - /* Might as well exit boot services now */ - status = efi_call_phys2(sys_table->boottime->exit_boot_services, - handle, key); - 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; + while (data && data->next) + data = (struct setup_data *)(unsigned long)data->next; - called_exit = true; - efi_call_phys1(sys_table->boottime->free_pool, mem_map); - goto get_map; - } + if (data) + data->next = (unsigned long)e820ext; + else + params->hdr.setup_data = (unsigned long)e820ext; +} - /* Historic? */ - boot_params->alt_mem_k = 32 * 1024; +static efi_