Re: [PATCH] EFI loader: remove dead code
On Tue, Nov 01, 2016 at 08:38:08PM +0300, Eugene Korenevsky wrote: > *e820ext is always NULL in 'alloc_e820ext()' (see the code of 'exit_boot()'). > Therefore the 'if' condition is always false and the entire 'if' statement is > pointless. Remove it. > > --- > arch/x86/boot/compressed/eboot.c | 6 -- > 1 file changed, 6 deletions(-) > > diff --git a/arch/x86/boot/compressed/eboot.c > b/arch/x86/boot/compressed/eboot.c > index cc69e37..edfd4d6 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -956,12 +956,6 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct > setup_data **e820ext, > size = sizeof(struct setup_data) + > sizeof(struct e820entry) * nr_desc; > > - if (*e820ext) { > - efi_call_early(free_pool, *e820ext); > - *e820ext = NULL; > - *e820ext_size = 0; > - } > - I agree with your reading of the code. On the other hand, alloc_e820ext() has no knowledge of the 'first' flag used in exit_boot_func() so the call to free provides some assurance that memory isn't leaked if the calling code is changed. If the caller is responsible for freeing the memory in such a case, then alloc_e820ext() should at least return an error. -- Linn
Re: [PATCH] EFI loader: remove dead code
On Tue, Nov 01, 2016 at 08:38:08PM +0300, Eugene Korenevsky wrote: > *e820ext is always NULL in 'alloc_e820ext()' (see the code of 'exit_boot()'). > Therefore the 'if' condition is always false and the entire 'if' statement is > pointless. Remove it. > > --- > arch/x86/boot/compressed/eboot.c | 6 -- > 1 file changed, 6 deletions(-) > > diff --git a/arch/x86/boot/compressed/eboot.c > b/arch/x86/boot/compressed/eboot.c > index cc69e37..edfd4d6 100644 > --- a/arch/x86/boot/compressed/eboot.c > +++ b/arch/x86/boot/compressed/eboot.c > @@ -956,12 +956,6 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct > setup_data **e820ext, > size = sizeof(struct setup_data) + > sizeof(struct e820entry) * nr_desc; > > - if (*e820ext) { > - efi_call_early(free_pool, *e820ext); > - *e820ext = NULL; > - *e820ext_size = 0; > - } > - I agree with your reading of the code. On the other hand, alloc_e820ext() has no knowledge of the 'first' flag used in exit_boot_func() so the call to free provides some assurance that memory isn't leaked if the calling code is changed. If the caller is responsible for freeing the memory in such a case, then alloc_e820ext() should at least return an error. -- Linn
[tip:efi/core] efi/arm64: Check SetupMode when determining Secure Boot status
Commit-ID: 30d7bf034c034995f34dae265d96247f7f12044e Gitweb: http://git.kernel.org/tip/30d7bf034c034995f34dae265d96247f7f12044e Author: Linn Crosetto <l...@hpe.com> AuthorDate: Mon, 25 Apr 2016 21:06:37 +0100 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 28 Apr 2016 11:33:49 +0200 efi/arm64: Check SetupMode when determining Secure Boot status According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Plus also do minor cleanup, change sizeof() use to match kernel style guidelines. Signed-off-by: Linn Crosetto <l...@hpe.com> Signed-off-by: Matt Fleming <m...@codeblueprint.co.uk> Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org> Acked-by: Mark Rutland <mark.rutl...@arm.com> Cc: Borislav Petkov <b...@alien8.de> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Roy Franz <roy.fr...@linaro.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: linux-...@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-6-git-send-email-m...@codeblueprint.co.uk Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 07f967c..1286325 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -22,21 +22,39 @@ bool __nokaslr; static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR:
[tip:efi/core] efi/arm64: Check SetupMode when determining Secure Boot status
Commit-ID: 30d7bf034c034995f34dae265d96247f7f12044e Gitweb: http://git.kernel.org/tip/30d7bf034c034995f34dae265d96247f7f12044e Author: Linn Crosetto AuthorDate: Mon, 25 Apr 2016 21:06:37 +0100 Committer: Ingo Molnar CommitDate: Thu, 28 Apr 2016 11:33:49 +0200 efi/arm64: Check SetupMode when determining Secure Boot status According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Plus also do minor cleanup, change sizeof() use to match kernel style guidelines. Signed-off-by: Linn Crosetto Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Acked-by: Mark Rutland Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Roy Franz Cc: Thomas Gleixner Cc: linux-...@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-6-git-send-email-m...@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 07f967c..1286325 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -22,21 +22,39 @@ bool __nokaslr; static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR:
[tip:efi/core] efi/arm64: Report unexpected errors when determining Secure Boot status
Commit-ID: 73a6492589c87cd56707c8ac19eec78236c2d576 Gitweb: http://git.kernel.org/tip/73a6492589c87cd56707c8ac19eec78236c2d576 Author: Linn Crosetto <l...@hpe.com> AuthorDate: Mon, 25 Apr 2016 21:06:36 +0100 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Thu, 28 Apr 2016 11:33:48 +0200 efi/arm64: Report unexpected errors when determining Secure Boot status Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto <l...@hpe.com> Signed-off-by: Matt Fleming <m...@codeblueprint.co.uk> Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org> Acked-by: Mark Rutland <mark.rutl...@arm.com> Cc: Borislav Petkov <b...@alien8.de> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Roy Franz <roy.fr...@linaro.org> Cc: Thomas Gleixner <t...@linutronix.de> Cc: linux-...@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-5-git-send-email-m...@codeblueprint.co.uk Signed-off-by: Ingo Molnar <mi...@kernel.org> --- drivers/firmware/efi/libstub/arm-stub.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 414deb8..07f967c 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,7 +20,7 @@ bool __nokaslr; -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -39,8 +39,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -185,6 +189,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -250,12 +255,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + + if (secure_boot < 0) { + pr_efi_err(sys_table, + "could not determine UEFI Secure Boot status.\n"); + } + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { + pr_efi(sys_table, "Ignoring DTB from command line.\n"); } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=",
[tip:efi/core] efi/arm64: Report unexpected errors when determining Secure Boot status
Commit-ID: 73a6492589c87cd56707c8ac19eec78236c2d576 Gitweb: http://git.kernel.org/tip/73a6492589c87cd56707c8ac19eec78236c2d576 Author: Linn Crosetto AuthorDate: Mon, 25 Apr 2016 21:06:36 +0100 Committer: Ingo Molnar CommitDate: Thu, 28 Apr 2016 11:33:48 +0200 efi/arm64: Report unexpected errors when determining Secure Boot status Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto Signed-off-by: Matt Fleming Reviewed-by: Ard Biesheuvel Acked-by: Mark Rutland Cc: Borislav Petkov Cc: Peter Zijlstra Cc: Roy Franz Cc: Thomas Gleixner Cc: linux-...@vger.kernel.org Link: http://lkml.kernel.org/r/1461614832-17633-5-git-send-email-m...@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/arm-stub.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 414deb8..07f967c 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,7 +20,7 @@ bool __nokaslr; -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -39,8 +39,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -185,6 +189,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -250,12 +255,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + + if (secure_boot < 0) { + pr_efi_err(sys_table, + "could not determine UEFI Secure Boot status.\n"); + } + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { + pr_efi(sys_table, "Ignoring DTB from command line.\n"); } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=",
[PATCH v3 1/2] arm64/efi: report unexpected errors when determining Secure Boot status
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto <l...@hpe.com> --- v2: - Maintain existing behavior to allow 'dtb=' parameter only when UEFI Secure Boot is disabled and not in an unknown state. (Mark Rutland) v3: - Add prints to inform the user in the following two cases: failure to determine Secure Boot status, ignoring "dtb=" kernel parameter (Ard Biesheuvel) drivers/firmware/efi/libstub/arm-stub.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..1e98fb7 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -18,7 +18,7 @@ #include "efistub.h" -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -37,8 +37,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -183,6 +187,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -231,12 +236,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + + if (secure_boot < 0) { + pr_efi_err(sys_table, + "could not determine UEFI Secure Boot status.\n"); + } + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { + pr_efi(sys_table, "Ignoring DTB from command line.\n"); } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", -- 2.1.4
[PATCH v3 1/2] arm64/efi: report unexpected errors when determining Secure Boot status
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable() when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto --- v2: - Maintain existing behavior to allow 'dtb=' parameter only when UEFI Secure Boot is disabled and not in an unknown state. (Mark Rutland) v3: - Add prints to inform the user in the following two cases: failure to determine Secure Boot status, ignoring "dtb=" kernel parameter (Ard Biesheuvel) drivers/firmware/efi/libstub/arm-stub.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..1e98fb7 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -18,7 +18,7 @@ #include "efistub.h" -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -37,8 +37,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -183,6 +187,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -231,12 +236,21 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + + if (secure_boot < 0) { + pr_efi_err(sys_table, + "could not determine UEFI Secure Boot status.\n"); + } + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { + pr_efi(sys_table, "Ignoring DTB from command line.\n"); } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", -- 2.1.4
[PATCH v3 2/2] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Minor cleanup, change sizeof to match kernel style guidelines. Signed-off-by: Linn Crosetto <l...@hpe.com> --- v2: - Reformat quote from UEFI specification and note cleanup (Mark Rutland) - Restructure code on top of changes in patch 1/2 drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 1e98fb7..c049d41 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,21 +20,39 @@ static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR: -- 2.1.4
[PATCH v3 2/2] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Minor cleanup, change sizeof to match kernel style guidelines. Signed-off-by: Linn Crosetto --- v2: - Reformat quote from UEFI specification and note cleanup (Mark Rutland) - Restructure code on top of changes in patch 1/2 drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 1e98fb7..c049d41 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,21 +20,39 @@ static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR: -- 2.1.4
[PATCH v3 0/2] arm64/efi: query Secure Boot status according to UEFI spec
This series modifies the function that queries the status of UEFI Secure Boot in the EFI stub to match the UEFI specification, and allow the caller to determine if it is enabled, disabled, or in an unknown state due to an unexpected error from GetVariable(). v2: - Add return values for unexpected errors - Split changes into two patches v3: - Add more verbosity with additional prints Linn Crosetto (2): arm64/efi: report unexpected errors when determining Secure Boot status arm64/efi: check SetupMode when determining Secure Boot status drivers/firmware/efi/libstub/arm-stub.c | 54 ++--- 1 file changed, 43 insertions(+), 11 deletions(-) -- 2.1.4
[PATCH v3 0/2] arm64/efi: query Secure Boot status according to UEFI spec
This series modifies the function that queries the status of UEFI Secure Boot in the EFI stub to match the UEFI specification, and allow the caller to determine if it is enabled, disabled, or in an unknown state due to an unexpected error from GetVariable(). v2: - Add return values for unexpected errors - Split changes into two patches v3: - Add more verbosity with additional prints Linn Crosetto (2): arm64/efi: report unexpected errors when determining Secure Boot status arm64/efi: check SetupMode when determining Secure Boot status drivers/firmware/efi/libstub/arm-stub.c | 54 ++--- 1 file changed, 43 insertions(+), 11 deletions(-) -- 2.1.4
[PATCH v2 2/2] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Minor cleanup, change sizeof to match kernel style guidelines. Signed-off-by: Linn Crosetto <l...@hpe.com> --- v2: - Reformat quote from UEFI specification and note cleanup (Mark Rutland) - Restructure code on top of changes in patch 1/2 drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index b1bb133..19e54d4 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,21 +20,39 @@ static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR: -- 2.1.4
[PATCH v2 2/2] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification (version 2.5 Errata A, page 87): The platform firmware is operating in secure boot mode if the value of the SetupMode variable is 0 and the SecureBoot variable is set to 1. A platform cannot operate in secure boot mode if the SetupMode variable is set to 1. Check the value of the SetupMode variable when determining the state of Secure Boot. Minor cleanup, change sizeof to match kernel style guidelines. Signed-off-by: Linn Crosetto --- v2: - Reformat quote from UEFI specification and note cleanup (Mark Rutland) - Restructure code on top of changes in patch 1/2 drivers/firmware/efi/libstub/arm-stub.c | 32 +--- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index b1bb133..19e54d4 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,21 +20,39 @@ static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + goto out_efi_err; + + if (val == 1) + return 0; + + return 1; + +out_efi_err: switch (status) { - case EFI_SUCCESS: - return val; case EFI_NOT_FOUND: return 0; case EFI_DEVICE_ERROR: -- 2.1.4
[PATCH v2 0/2] arm64/efi: query Secure Boot status according to UEFI spec
This series modifies the function that queries the status of UEFI Secure Boot in the EFI stub to match the UEFI specification, and allow the caller to determine if it is enabled, disabled, or in an unknown state due to an unexpected error from GetVariable(). v2: - Add return values for unexpected errors - Split changes into two patches Linn Crosetto (2): arm64/efi: report unexpected errors when determining Secure Boot status arm64/efi: check SetupMode when determining Secure Boot status drivers/firmware/efi/libstub/arm-stub.c | 49 + 1 file changed, 37 insertions(+), 12 deletions(-) -- 2.1.4
[PATCH v2 1/2] arm64/efi: report unexpected errors when determining Secure Boot status
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto <l...@hpe.com> --- New patch in v2 based on feedback from v1: - Maintain existing behavior to allow 'dtb=' parameter only when UEFI Secure Boot is disabled and not in an unknown state. (Mark Rutland) drivers/firmware/efi/libstub/arm-stub.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..b1bb133 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -18,7 +18,7 @@ #include "efistub.h" -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -37,8 +37,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -183,6 +187,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -231,13 +236,15 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); - } else { + if (secure_boot == 0) { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", ~0UL, _addr, _size); -- 2.1.4
[PATCH v2 0/2] arm64/efi: query Secure Boot status according to UEFI spec
This series modifies the function that queries the status of UEFI Secure Boot in the EFI stub to match the UEFI specification, and allow the caller to determine if it is enabled, disabled, or in an unknown state due to an unexpected error from GetVariable(). v2: - Add return values for unexpected errors - Split changes into two patches Linn Crosetto (2): arm64/efi: report unexpected errors when determining Secure Boot status arm64/efi: check SetupMode when determining Secure Boot status drivers/firmware/efi/libstub/arm-stub.c | 49 + 1 file changed, 37 insertions(+), 12 deletions(-) -- 2.1.4
[PATCH v2 1/2] arm64/efi: report unexpected errors when determining Secure Boot status
Certain code in the boot path may require the ability to determine whether UEFI Secure Boot is definitely enabled, for example printing status to the console. Other code may need to know when UEFI Secure Boot is definitely disabled, for example restricting use of kernel parameters. If an unexpected error is returned from GetVariable when querying the status of UEFI Secure Boot, return an error to the caller. This allows the caller to determine the definite state, and to take appropriate action if an expected error is returned. Signed-off-by: Linn Crosetto --- New patch in v2 based on feedback from v1: - Maintain existing behavior to allow 'dtb=' parameter only when UEFI Secure Boot is disabled and not in an unknown state. (Mark Rutland) drivers/firmware/efi/libstub/arm-stub.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..b1bb133 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -18,7 +18,7 @@ #include "efistub.h" -static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; static efi_char16_t const var_name[] = { @@ -37,8 +37,12 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) return val; case EFI_NOT_FOUND: return 0; + case EFI_DEVICE_ERROR: + return -EIO; + case EFI_SECURITY_VIOLATION: + return -EACCES; default: - return 1; + return -EINVAL; } } @@ -183,6 +187,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + int secure_boot = 0; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -231,13 +236,15 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (status != EFI_SUCCESS) pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); + secure_boot = efi_get_secureboot(sys_table); + if (secure_boot > 0) + pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); + /* * Unauthenticated device tree data is a security hazard, so * ignore 'dtb=' unless UEFI Secure Boot is disabled. */ - if (efi_secureboot_enabled(sys_table)) { - pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); - } else { + if (secure_boot == 0) { status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=", ~0UL, _addr, _size); -- 2.1.4
[PATCH] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification, the platform is operating in secure boot mode if SetupMode is 0 and SecureBoot is 1, and cannot operate in secure boot mode if SetupMode is set to 1. Check the value of SetupMode when determining the state of Secure Boot. Signed-off-by: Linn Crosetto <l...@hpe.com> --- drivers/firmware/efi/libstub/arm-stub.c | 34 + 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..7ef2e20 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,26 +20,36 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); - switch (status) { - case EFI_SUCCESS: - return val; - case EFI_NOT_FOUND: + if (status != EFI_SUCCESS) return 0; - default: - return 1; - } + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + return 0; + + if (val == 1) + return 0; + + return 1; } efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, -- 2.1.4
[PATCH] arm64/efi: check SetupMode when determining Secure Boot status
According to the UEFI specification, the platform is operating in secure boot mode if SetupMode is 0 and SecureBoot is 1, and cannot operate in secure boot mode if SetupMode is set to 1. Check the value of SetupMode when determining the state of Secure Boot. Signed-off-by: Linn Crosetto --- drivers/firmware/efi/libstub/arm-stub.c | 34 + 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 3397902..7ef2e20 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -20,26 +20,36 @@ static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg) { - static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID; - static efi_char16_t const var_name[] = { + static efi_char16_t const sb_var_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t const sm_var_name[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; - unsigned long size = sizeof(u8); - efi_status_t status; u8 val; + unsigned long size = sizeof(val); + efi_status_t status; - status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)_guid, + status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)_guid, NULL, , ); - switch (status) { - case EFI_SUCCESS: - return val; - case EFI_NOT_FOUND: + if (status != EFI_SUCCESS) return 0; - default: - return 1; - } + + if (val == 0) + return 0; + + status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)_guid, + NULL, , ); + + if (status != EFI_SUCCESS) + return 0; + + if (val == 1) + return 0; + + return 1; } efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, -- 2.1.4
Re: [PATCH v3] x86, irq: get correct available vectors for cpu disable
On Wed, Mar 26, 2014 at 10:04:52AM -0700, Yinghai Lu wrote: > On Wed, Mar 26, 2014 at 9:50 AM, Linn Crosetto wrote: > > On Tue, Mar 25, 2014 at 05:18:53PM -0700, Yinghai Lu wrote: > > > > Just noting that not all bits above first_system_vector are set in the > > bitmap, > > so the comment in asm/desc.h and the change log could be misleading: > > > > /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ > > > > Do you mean some vector that is neither used by percpu_vector_irq nor > system_vector > after first_system_vector ? Yes, that is the case. In my previous example, first_system_vector is 239, but test_bit(240, used_vectors) would return unset, though it cannot be used by percpu vector_irq. If it marked all vectors unusable by percpu vector_irq, then all bits above first_system_vector would be set. > Anyway if bit is set in used_vectors, that vector can not be used by > percpu vector_irq. > > so that statement looks still right. > > Feel free to suggest right comment or changelog. The following might be more accurate: /* * The used_vectors BITMAP marks IRQs not managed by percpu vector_irq, below * first_system_vector. Vectors above first_system_vector are not managed by * percpu vector_irq. */ -- 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: [PATCH v3] x86, irq: get correct available vectors for cpu disable
On Tue, Mar 25, 2014 at 05:18:53PM -0700, Yinghai Lu wrote: > On Tue, Mar 25, 2014 at 1:03 PM, Linn Crosetto wrote: > > Thanks for the patch. > > > > On Tue, Jan 28, 2014 at 01:54:05PM -0800, Yinghai Lu wrote: > >> used_vectors is a bitmap for vectors that are not tracked in per_cpu > >> vector_irq. > > > > I feel like this comment (also in the code) could be misleading because > > vectors > > above first_system_vector are effectively not tracked in per_cpu > > vector_irq, but > > also may not have the bit set in used_vectors. For example, used_vectors > > from a > > system that I am looking at now: > > > > first_system_vector > > 239 255 > > | | > > 10 01000 1 1 > > > > test_bit(240, used_vectors) does not return the correct answer to the > > question > > about whether the vector is tracked in per_cpu vector_irq. This leads to two > > meanings for the bitmap; for vectors less than first_system_vector whether > > or > > not they are tracked in per_cpu vector_irq, and for vectors above > > first_system_vector, whether or not they are in use: > > > > static inline int is_per_cpu_vector(int vector) { > > return !test_bit(vector, used_vectors) && > > vector < first_system_vector; > > } > > sorry, I can not catch what you want to say. > > Do you mean the change log or comment in the patch is not right? Just noting that not all bits above first_system_vector are set in the bitmap, so the comment in asm/desc.h and the change log could be misleading: /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ I have tested and the patch itself is good. Thanks, Linn -- 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: [PATCH v3] x86, irq: get correct available vectors for cpu disable
On Tue, Mar 25, 2014 at 05:18:53PM -0700, Yinghai Lu wrote: On Tue, Mar 25, 2014 at 1:03 PM, Linn Crosetto l...@hp.com wrote: Thanks for the patch. On Tue, Jan 28, 2014 at 01:54:05PM -0800, Yinghai Lu wrote: used_vectors is a bitmap for vectors that are not tracked in per_cpu vector_irq. I feel like this comment (also in the code) could be misleading because vectors above first_system_vector are effectively not tracked in per_cpu vector_irq, but also may not have the bit set in used_vectors. For example, used_vectors from a system that I am looking at now: first_system_vector 239 255 | | 10 01000 1 1 test_bit(240, used_vectors) does not return the correct answer to the question about whether the vector is tracked in per_cpu vector_irq. This leads to two meanings for the bitmap; for vectors less than first_system_vector whether or not they are tracked in per_cpu vector_irq, and for vectors above first_system_vector, whether or not they are in use: static inline int is_per_cpu_vector(int vector) { return !test_bit(vector, used_vectors) vector first_system_vector; } sorry, I can not catch what you want to say. Do you mean the change log or comment in the patch is not right? Just noting that not all bits above first_system_vector are set in the bitmap, so the comment in asm/desc.h and the change log could be misleading: /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ I have tested and the patch itself is good. Thanks, Linn -- 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: [PATCH v3] x86, irq: get correct available vectors for cpu disable
On Wed, Mar 26, 2014 at 10:04:52AM -0700, Yinghai Lu wrote: On Wed, Mar 26, 2014 at 9:50 AM, Linn Crosetto l...@hp.com wrote: On Tue, Mar 25, 2014 at 05:18:53PM -0700, Yinghai Lu wrote: Just noting that not all bits above first_system_vector are set in the bitmap, so the comment in asm/desc.h and the change log could be misleading: /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ Do you mean some vector that is neither used by percpu_vector_irq nor system_vector after first_system_vector ? Yes, that is the case. In my previous example, first_system_vector is 239, but test_bit(240, used_vectors) would return unset, though it cannot be used by percpu vector_irq. If it marked all vectors unusable by percpu vector_irq, then all bits above first_system_vector would be set. Anyway if bit is set in used_vectors, that vector can not be used by percpu vector_irq. so that statement looks still right. Feel free to suggest right comment or changelog. The following might be more accurate: /* * The used_vectors BITMAP marks IRQs not managed by percpu vector_irq, below * first_system_vector. Vectors above first_system_vector are not managed by * percpu vector_irq. */ -- 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: [PATCH v3] x86, irq: get correct available vectors for cpu disable
Thanks for the patch. On Tue, Jan 28, 2014 at 01:54:05PM -0800, Yinghai Lu wrote: > used_vectors is a bitmap for vectors that are not tracked in per_cpu > vector_irq. I feel like this comment (also in the code) could be misleading because vectors above first_system_vector are effectively not tracked in per_cpu vector_irq, but also may not have the bit set in used_vectors. For example, used_vectors from a system that I am looking at now: first_system_vector 239 255 | | 10 01000 1 1 test_bit(240, used_vectors) does not return the correct answer to the question about whether the vector is tracked in per_cpu vector_irq. This leads to two meanings for the bitmap; for vectors less than first_system_vector whether or not they are tracked in per_cpu vector_irq, and for vectors above first_system_vector, whether or not they are in use: static inline int is_per_cpu_vector(int vector) { return !test_bit(vector, used_vectors) && vector < first_system_vector; } Thanks, Linn > used_vectors contains information on the first 32 exceptions, the system > vectors. > the IA32_SYSCALL_VECTOR (0x80), and the IRQ_MOVE_CLEANUP_VECTOR (0x20). > > assign_irq_vectors() assigns vectors up to first_system_vector and > it will not use vectors that are set used_vectors. > > This patch modifies the code to scan up to first_system_vector > and do a test on the used_vectors bitmap. > > So count avaiable vectors correctly. > > -v2: fix compiling problem. > -v3: update changelog and commets > > Signed-off-by: Yinghai Lu > > --- > arch/x86/kernel/irq.c | 18 -- > 1 file changed, 16 insertions(+), 2 deletions(-) > > Index: linux-2.6/arch/x86/kernel/irq.c > === > --- linux-2.6.orig/arch/x86/kernel/irq.c > +++ linux-2.6/arch/x86/kernel/irq.c > @@ -17,6 +17,7 @@ > #include > #include > #include > +#include > > #define CREATE_TRACE_POINTS > #include > @@ -321,8 +322,21 @@ int check_irq_vectors_for_cpu_disable(vo > for_each_online_cpu(cpu) { > if (cpu == this_cpu) > continue; > - for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; > - vector++) { > + > + /* > + * assign_irq_vector() only scan per_cpu vectors from > + * FIRST_EXTERNAL_VECTOR to first_system_vector. > + * It aslo skip vectors that are set in used_vectors bitmask. > + * used_vectors could have bits set for > + * IA32_SYSCALL_VECTOR (0x80) > + * IRQ_MOVE_CLEANUP_VECTOR (0x20) > + * Don't count those as available vectors. > + */ > + for (vector = FIRST_EXTERNAL_VECTOR; > + vector < first_system_vector; vector++) { > + if (test_bit(vector, used_vectors)) > + continue; > + > if (per_cpu(vector_irq, cpu)[vector] < 0) > count++; > } -- 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: [PATCH v3] x86, irq: get correct available vectors for cpu disable
Thanks for the patch. On Tue, Jan 28, 2014 at 01:54:05PM -0800, Yinghai Lu wrote: used_vectors is a bitmap for vectors that are not tracked in per_cpu vector_irq. I feel like this comment (also in the code) could be misleading because vectors above first_system_vector are effectively not tracked in per_cpu vector_irq, but also may not have the bit set in used_vectors. For example, used_vectors from a system that I am looking at now: first_system_vector 239 255 | | 10 01000 1 1 test_bit(240, used_vectors) does not return the correct answer to the question about whether the vector is tracked in per_cpu vector_irq. This leads to two meanings for the bitmap; for vectors less than first_system_vector whether or not they are tracked in per_cpu vector_irq, and for vectors above first_system_vector, whether or not they are in use: static inline int is_per_cpu_vector(int vector) { return !test_bit(vector, used_vectors) vector first_system_vector; } Thanks, Linn used_vectors contains information on the first 32 exceptions, the system vectors. the IA32_SYSCALL_VECTOR (0x80), and the IRQ_MOVE_CLEANUP_VECTOR (0x20). assign_irq_vectors() assigns vectors up to first_system_vector and it will not use vectors that are set used_vectors. This patch modifies the code to scan up to first_system_vector and do a test on the used_vectors bitmap. So count avaiable vectors correctly. -v2: fix compiling problem. -v3: update changelog and commets Signed-off-by: Yinghai Lu ying...@kernel.org --- arch/x86/kernel/irq.c | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) Index: linux-2.6/arch/x86/kernel/irq.c === --- linux-2.6.orig/arch/x86/kernel/irq.c +++ linux-2.6/arch/x86/kernel/irq.c @@ -17,6 +17,7 @@ #include asm/idle.h #include asm/mce.h #include asm/hw_irq.h +#include asm/desc.h #define CREATE_TRACE_POINTS #include asm/trace/irq_vectors.h @@ -321,8 +322,21 @@ int check_irq_vectors_for_cpu_disable(vo for_each_online_cpu(cpu) { if (cpu == this_cpu) continue; - for (vector = FIRST_EXTERNAL_VECTOR; vector NR_VECTORS; - vector++) { + + /* + * assign_irq_vector() only scan per_cpu vectors from + * FIRST_EXTERNAL_VECTOR to first_system_vector. + * It aslo skip vectors that are set in used_vectors bitmask. + * used_vectors could have bits set for + * IA32_SYSCALL_VECTOR (0x80) + * IRQ_MOVE_CLEANUP_VECTOR (0x20) + * Don't count those as available vectors. + */ + for (vector = FIRST_EXTERNAL_VECTOR; + vector first_system_vector; vector++) { + if (test_bit(vector, used_vectors)) + continue; + if (per_cpu(vector_irq, cpu)[vector] 0) count++; } -- 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: [PATCH v3 4/4] x86: Pass memory range via E820 for kdump
On Fri, Mar 14, 2014 at 08:26:15AM +, Matt Fleming wrote: > On Fri, 14 Mar, at 10:47:26AM, Dave Young wrote: > > > > Can you test with matt's tree to see if it works? > > If it still happens please post the full log. > > So that'd be the 'next' branch at, > > git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git > > which contains Borislav's fixes for the EFI memmap code. I believe I included those fixes when testing with 3.14 rc6, adding: https://lkml.org/lkml/2014/3/8/209 92b71d8 52d201e a52f515 b660133 e91925d Since this testing was done on a prototype, I will send you the log in a separate email. I tried efi.git/next (with the addition of 4ce7a86), and hit the same panic. -- 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: [PATCH v3 4/4] x86: Pass memory range via E820 for kdump
On Fri, Mar 14, 2014 at 08:26:15AM +, Matt Fleming wrote: On Fri, 14 Mar, at 10:47:26AM, Dave Young wrote: Can you test with matt's tree to see if it works? If it still happens please post the full log. So that'd be the 'next' branch at, git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git which contains Borislav's fixes for the EFI memmap code. I believe I included those fixes when testing with 3.14 rc6, adding: https://lkml.org/lkml/2014/3/8/209 92b71d8 52d201e a52f515 b660133 e91925d Since this testing was done on a prototype, I will send you the log in a separate email. I tried efi.git/next (with the addition of 4ce7a86), and hit the same panic. -- 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 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, 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 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 l...@hp.com --- 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/
[PATCHv3] 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 --- 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(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..bfa177a 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,46 +982,198 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext->type = SETUP_E820_EXT; + e820ext->len = nr_entries * sizeof(struct e820entry); + e820ext->next = 0; + + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; + + while (data && data->next) + data = (struct setup_data *)(unsigned long)data->next; + + if (data) + data->next = (unsigned long)e820ext; + else + params->hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = >e820_map[0]; + struct efi_info *efi = >efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size; + + for (i = 0; i < nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi->efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); + switch (d->type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev && prev->type == e820_type && + (prev->addr + prev->size) == d->phys_addr) { + prev->size += d->num_pages << 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params->e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size < need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext->data; + } + + e820_map->addr = d->phys_addr; + e820_map->size = d->num_pages << PAGE_SHIFT; + e820_map->type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries > ARRAY_SIZE(params->e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params->e82
Re: [PATCHv2] x86: EFI stub support for large memory maps
On Tue, Sep 17, 2013 at 09:14:52PM +0100, Matt Fleming wrote: > > +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, > > + u32 *e820ext_size) > > +{ > > + efi_status_t status; > > + unsigned long size; > > + > > + size = sizeof(struct setup_data) + > > + sizeof(struct e820entry) * nr_desc; > > + > > + if (*e820ext && size <= *e820ext_size) > > + return EFI_SUCCESS; /* Already allocated */ > > Do we actually need this check? I thought the 'prev_nr_desc' below > ensures we only allocate 'e820ext' if we need more memory. I am okay with removing the check. There is another bug in exit_boot, when jumping to get_map the call to get the memory map is passed the previous map size instead of the size of the allocated buffer. I'll make the changes and resend. > > [...] > > > @@ -1016,6 +1157,19 @@ get_map: > > if (status != EFI_SUCCESS) > > goto free_mem_map; > > > > + prev_nr_desc = nr_desc; > > + nr_desc = size / desc_size; > > + if (nr_desc > prev_nr_desc && > > + nr_desc > ARRAY_SIZE(boot_params->e820_map)) { > > + u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params->e820_map); > > + > > + status = alloc_e820ext(nr_e820ext, , _size); > > + if (status != EFI_SUCCESS) > > + goto free_mem_map; > > + > > + goto get_map; /* Allocated memory, get map again */ > > + } > > + -- 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: [PATCHv2] x86: EFI stub support for large memory maps
On Tue, Sep 17, 2013 at 09:14:52PM +0100, Matt Fleming wrote: +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, + u32 *e820ext_size) +{ + efi_status_t status; + unsigned long size; + + size = sizeof(struct setup_data) + + sizeof(struct e820entry) * nr_desc; + + if (*e820ext size = *e820ext_size) + return EFI_SUCCESS; /* Already allocated */ Do we actually need this check? I thought the 'prev_nr_desc' below ensures we only allocate 'e820ext' if we need more memory. I am okay with removing the check. There is another bug in exit_boot, when jumping to get_map the call to get the memory map is passed the previous map size instead of the size of the allocated buffer. I'll make the changes and resend. [...] @@ -1016,6 +1157,19 @@ get_map: if (status != EFI_SUCCESS) goto free_mem_map; + prev_nr_desc = nr_desc; + nr_desc = size / desc_size; + if (nr_desc prev_nr_desc + nr_desc ARRAY_SIZE(boot_params-e820_map)) { + u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params-e820_map); + + status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size); + if (status != EFI_SUCCESS) + goto free_mem_map; + + goto get_map; /* Allocated memory, get map again */ + } + -- 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/
[PATCHv3] 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 l...@hp.com --- 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(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..bfa177a 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,46 +982,198 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext-type = SETUP_E820_EXT; + e820ext-len = nr_entries * sizeof(struct e820entry); + e820ext-next = 0; + + data = (struct setup_data *)(unsigned long)params-hdr.setup_data; + + while (data data-next) + data = (struct setup_data *)(unsigned long)data-next; + + if (data) + data-next = (unsigned long)e820ext; + else + params-hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = params-e820_map[0]; + struct efi_info *efi = params-efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi-efi_memmap_size / efi-efi_memdesc_size; + + for (i = 0; i nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi-efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi-efi_memdesc_size)); + switch (d-type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev prev-type == e820_type + (prev-addr + prev-size) == d-phys_addr) { + prev-size += d-num_pages 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params-e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext-data; + } + + e820_map-addr = d-phys_addr; + e820_map-size = d-num_pages PAGE_SHIFT; + e820_map-type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries ARRAY_SIZE(params-e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params-e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params-e820_entries = (u8)nr_entries; + + return EFI_SUCCESS; +} + +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, + u32
[PATCH 2/3] x86: fix sparse warning in parse_e820_ext()
Replace the call to early_iounmap() with early_memunmap() to eliminate the following sparse warning: arch/x86/kernel/e820.c:672:23: sparse: incorrect type in argument 1 (different address spaces) Signed-off-by: Linn Crosetto --- arch/x86/kernel/e820.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 174da5f..06e0c4a 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -669,7 +669,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len) extmap = (struct e820entry *)(sdata->data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), _map); - early_iounmap(sdata, data_len); + early_memunmap(sdata, data_len); printk(KERN_INFO "e820: extended physical RAM map:\n"); e820_print_map("extended"); } -- 1.7.11.3 -- 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/
[PATCH 3/3] x86: fix early_iounmap() sparse warnings in setup.c
Replace calls to early_iounmap() with early_memunmap() for pointers mapped with early_memremap() to eliminate the following sparse warnings: arch/x86/kernel/setup.c:355:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:441:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:470:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:491:31: warning: incorrect type in argument 1 (different address spaces) Signed-off-by: Linn Crosetto --- arch/x86/kernel/setup.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f0de629..3081fc6 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -352,7 +352,7 @@ static void __init relocate_initrd(void) mapaddr = ramdisk_image & PAGE_MASK; p = early_memremap(mapaddr, clen+slop); memcpy(q, p+slop, clen); - early_iounmap(p, clen+slop); + early_memunmap(p, clen+slop); q += clen; ramdisk_image += clen; ramdisk_size -= clen; @@ -438,7 +438,7 @@ static void __init parse_setup_data(void) data_len = data->len + sizeof(struct setup_data); data_type = data->type; pa_next = data->next; - early_iounmap(data, map_len); + early_memunmap(data, map_len); switch (data_type) { case SETUP_E820_EXT: @@ -467,7 +467,7 @@ static void __init e820_reserve_setup_data(void) E820_RAM, E820_RESERVED_KERN); found = 1; pa_data = data->next; - early_iounmap(data, sizeof(*data)); + early_memunmap(data, sizeof(*data)); } if (!found) return; @@ -488,7 +488,7 @@ static void __init memblock_x86_reserve_range_setup_data(void) data = early_memremap(pa_data, sizeof(*data)); memblock_reserve(pa_data, sizeof(*data) + data->len); pa_data = data->next; - early_iounmap(data, sizeof(*data)); + early_memunmap(data, sizeof(*data)); } } -- 1.7.11.3 -- 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/
[PATCH 1/3] x86/mm: fix sparse warnings from early_memremap()
This patch creates consistent early interfaces for mapping normal memory and eliminates some sparse warnings. early_memremap() was created to map normal memory, as opposed to the ioremap interfaces for actual IO mappings, so remove the __iomem annotation from early_memremap(). In addition, early_memunmap() is added to provide an interface analogous to early_iounmap() for normal memory. Fixes the following warnings: arch/x86/kernel/setup.c:353:19: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:437:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:465:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:488:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/e820.c:667:15: warning: incorrect type in assignment (different address spaces) Signed-off-by: Linn Crosetto --- arch/x86/include/asm/io.h | 4 ++-- arch/x86/mm/ioremap.c | 9 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 34f69cb..ae1ef3e 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -325,8 +325,8 @@ extern void early_ioremap_init(void); extern void early_ioremap_reset(void); extern void __iomem *early_ioremap(resource_size_t phys_addr, unsigned long size); -extern void __iomem *early_memremap(resource_size_t phys_addr, - unsigned long size); +extern void *early_memremap(resource_size_t phys_addr, unsigned long size); +extern void early_memunmap(void *addr, unsigned long size); extern void early_iounmap(void __iomem *addr, unsigned long size); extern void fixup_early_ioremap(void); extern bool is_early_ioremap_ptep(pte_t *ptep); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 799580c..a144929 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -562,10 +562,15 @@ early_ioremap(resource_size_t phys_addr, unsigned long size) } /* Remap memory */ -void __init __iomem * +void __init * early_memremap(resource_size_t phys_addr, unsigned long size) { - return __early_ioremap(phys_addr, size, PAGE_KERNEL); + return (__force void *)__early_ioremap(phys_addr, size, PAGE_KERNEL); +} + +void __init early_memunmap(void *addr, unsigned long size) +{ + early_iounmap((void __iomem *)addr, size); } void __init early_iounmap(void __iomem *addr, unsigned long size) -- 1.7.11.3 -- 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/
[PATCH 0/3] x86/mm: fix early_memremap() sparse warnings
This set of patches cleans up some sparse warnings generated by callers of early_memremap(). early_memremap() was created as an interface to to map normal memory (commit 1494177), in contrast to early_ioremap() for IO mappings. Later on, early_memremap() was annotated with __iomem (commit 1d6cf1f) which generates sparse warnings for callers using pointers not declared with __iomem. Callers of early_memremap() were expected to use early_iounmap() to remove the mapping, which generates more sparse warnings as the argument to early_iounmap() is also annotated with __iomem. To clean this up, remove __iomem from early_memremap() and create early_memunmap() to be used for removing normal memory mappings. Removes the following warnings: arch/x86/kernel/setup.c:353:19: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:355:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:437:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:441:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:465:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:470:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:488:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:491:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/e820.c:667:15: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/e820.c:672:23: warning: incorrect type in argument 1 (different address spaces) Linn Crosetto (3): x86/mm: fix sparse warnings from early_memremap() x86: fix sparse warning in parse_e820_ext() x86: fix early_iounmap() sparse warnings in setup.c arch/x86/include/asm/io.h | 4 ++-- arch/x86/kernel/e820.c| 2 +- arch/x86/kernel/setup.c | 8 arch/x86/mm/ioremap.c | 9 +++-- 4 files changed, 14 insertions(+), 9 deletions(-) -- 1.7.11.3 -- 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/
[PATCHv2] 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 --- Changes in v2: * Free memory when error is returned from alloc_e820ext() as suggested by Matt Fleming * Set pointer to NULL and size to 0 after freeing memory in alloc_e820ext() arch/x86/boot/compressed/eboot.c | 223 --- 1 file changed, 160 insertions(+), 63 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..2ac395e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,20 +982,161 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext->type = SETUP_E820_EXT; + e820ext->len = nr_entries * sizeof(struct e820entry); + e820ext->next = 0; + + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; + + while (data && data->next) + data = (struct setup_data *)(unsigned long)data->next; + + if (data) + data->next = (unsigned long)e820ext; + else + params->hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = >e820_map[0]; + struct efi_info *efi = >efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size; + + for (i = 0; i < nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi->efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); + switch (d->type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev && prev->type == e820_type && + (prev->addr + prev->size) == d->phys_addr) { + prev->size += d->num_pages << 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params->e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size < need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext->data; + } + + e820_map->addr = d->phys_addr; + e820_map->size = d->num_pages << PAGE_SHIFT; + e820_map->type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries > ARRAY_SIZE(params->e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params->e82
[PATCHv2] 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 l...@hp.com --- Changes in v2: * Free memory when error is returned from alloc_e820ext() as suggested by Matt Fleming * Set pointer to NULL and size to 0 after freeing memory in alloc_e820ext() arch/x86/boot/compressed/eboot.c | 223 --- 1 file changed, 160 insertions(+), 63 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..2ac395e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,20 +982,161 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext-type = SETUP_E820_EXT; + e820ext-len = nr_entries * sizeof(struct e820entry); + e820ext-next = 0; + + data = (struct setup_data *)(unsigned long)params-hdr.setup_data; + + while (data data-next) + data = (struct setup_data *)(unsigned long)data-next; + + if (data) + data-next = (unsigned long)e820ext; + else + params-hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = params-e820_map[0]; + struct efi_info *efi = params-efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi-efi_memmap_size / efi-efi_memdesc_size; + + for (i = 0; i nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi-efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi-efi_memdesc_size)); + switch (d-type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev prev-type == e820_type + (prev-addr + prev-size) == d-phys_addr) { + prev-size += d-num_pages 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params-e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext-data; + } + + e820_map-addr = d-phys_addr; + e820_map-size = d-num_pages PAGE_SHIFT; + e820_map-type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries ARRAY_SIZE(params-e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params-e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params-e820_entries = (u8)nr_entries; + + return EFI_SUCCESS; +} + +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, + u32 *e820ext_size
[PATCH 0/3] x86/mm: fix early_memremap() sparse warnings
This set of patches cleans up some sparse warnings generated by callers of early_memremap(). early_memremap() was created as an interface to to map normal memory (commit 1494177), in contrast to early_ioremap() for IO mappings. Later on, early_memremap() was annotated with __iomem (commit 1d6cf1f) which generates sparse warnings for callers using pointers not declared with __iomem. Callers of early_memremap() were expected to use early_iounmap() to remove the mapping, which generates more sparse warnings as the argument to early_iounmap() is also annotated with __iomem. To clean this up, remove __iomem from early_memremap() and create early_memunmap() to be used for removing normal memory mappings. Removes the following warnings: arch/x86/kernel/setup.c:353:19: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:355:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:437:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:441:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:465:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:470:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:488:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:491:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/e820.c:667:15: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/e820.c:672:23: warning: incorrect type in argument 1 (different address spaces) Linn Crosetto (3): x86/mm: fix sparse warnings from early_memremap() x86: fix sparse warning in parse_e820_ext() x86: fix early_iounmap() sparse warnings in setup.c arch/x86/include/asm/io.h | 4 ++-- arch/x86/kernel/e820.c| 2 +- arch/x86/kernel/setup.c | 8 arch/x86/mm/ioremap.c | 9 +++-- 4 files changed, 14 insertions(+), 9 deletions(-) -- 1.7.11.3 -- 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/
[PATCH 1/3] x86/mm: fix sparse warnings from early_memremap()
This patch creates consistent early interfaces for mapping normal memory and eliminates some sparse warnings. early_memremap() was created to map normal memory, as opposed to the ioremap interfaces for actual IO mappings, so remove the __iomem annotation from early_memremap(). In addition, early_memunmap() is added to provide an interface analogous to early_iounmap() for normal memory. Fixes the following warnings: arch/x86/kernel/setup.c:353:19: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:437:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:465:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/setup.c:488:22: warning: incorrect type in assignment (different address spaces) arch/x86/kernel/e820.c:667:15: warning: incorrect type in assignment (different address spaces) Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/include/asm/io.h | 4 ++-- arch/x86/mm/ioremap.c | 9 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 34f69cb..ae1ef3e 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -325,8 +325,8 @@ extern void early_ioremap_init(void); extern void early_ioremap_reset(void); extern void __iomem *early_ioremap(resource_size_t phys_addr, unsigned long size); -extern void __iomem *early_memremap(resource_size_t phys_addr, - unsigned long size); +extern void *early_memremap(resource_size_t phys_addr, unsigned long size); +extern void early_memunmap(void *addr, unsigned long size); extern void early_iounmap(void __iomem *addr, unsigned long size); extern void fixup_early_ioremap(void); extern bool is_early_ioremap_ptep(pte_t *ptep); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 799580c..a144929 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -562,10 +562,15 @@ early_ioremap(resource_size_t phys_addr, unsigned long size) } /* Remap memory */ -void __init __iomem * +void __init * early_memremap(resource_size_t phys_addr, unsigned long size) { - return __early_ioremap(phys_addr, size, PAGE_KERNEL); + return (__force void *)__early_ioremap(phys_addr, size, PAGE_KERNEL); +} + +void __init early_memunmap(void *addr, unsigned long size) +{ + early_iounmap((void __iomem *)addr, size); } void __init early_iounmap(void __iomem *addr, unsigned long size) -- 1.7.11.3 -- 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/
[PATCH 2/3] x86: fix sparse warning in parse_e820_ext()
Replace the call to early_iounmap() with early_memunmap() to eliminate the following sparse warning: arch/x86/kernel/e820.c:672:23: sparse: incorrect type in argument 1 (different address spaces) Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/kernel/e820.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 174da5f..06e0c4a 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -669,7 +669,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len) extmap = (struct e820entry *)(sdata-data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), e820.nr_map); - early_iounmap(sdata, data_len); + early_memunmap(sdata, data_len); printk(KERN_INFO e820: extended physical RAM map:\n); e820_print_map(extended); } -- 1.7.11.3 -- 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/
[PATCH 3/3] x86: fix early_iounmap() sparse warnings in setup.c
Replace calls to early_iounmap() with early_memunmap() for pointers mapped with early_memremap() to eliminate the following sparse warnings: arch/x86/kernel/setup.c:355:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:441:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:470:31: warning: incorrect type in argument 1 (different address spaces) arch/x86/kernel/setup.c:491:31: warning: incorrect type in argument 1 (different address spaces) Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/kernel/setup.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f0de629..3081fc6 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -352,7 +352,7 @@ static void __init relocate_initrd(void) mapaddr = ramdisk_image PAGE_MASK; p = early_memremap(mapaddr, clen+slop); memcpy(q, p+slop, clen); - early_iounmap(p, clen+slop); + early_memunmap(p, clen+slop); q += clen; ramdisk_image += clen; ramdisk_size -= clen; @@ -438,7 +438,7 @@ static void __init parse_setup_data(void) data_len = data-len + sizeof(struct setup_data); data_type = data-type; pa_next = data-next; - early_iounmap(data, map_len); + early_memunmap(data, map_len); switch (data_type) { case SETUP_E820_EXT: @@ -467,7 +467,7 @@ static void __init e820_reserve_setup_data(void) E820_RAM, E820_RESERVED_KERN); found = 1; pa_data = data-next; - early_iounmap(data, sizeof(*data)); + early_memunmap(data, sizeof(*data)); } if (!found) return; @@ -488,7 +488,7 @@ static void __init memblock_x86_reserve_range_setup_data(void) data = early_memremap(pa_data, sizeof(*data)); memblock_reserve(pa_data, sizeof(*data) + data-len); pa_data = data-next; - early_iounmap(data, sizeof(*data)); + early_memunmap(data, sizeof(*data)); } } -- 1.7.11.3 -- 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/
[tip:x86/mm] x86: avoid remapping data in parse_setup_data()
Commit-ID: 30e46b574a1db7d14404e52dca8e1aa5f5155fd2 Gitweb: http://git.kernel.org/tip/30e46b574a1db7d14404e52dca8e1aa5f5155fd2 Author: Linn Crosetto AuthorDate: Tue, 13 Aug 2013 15:46:41 -0600 Committer: H. Peter Anvin CommitDate: Tue, 13 Aug 2013 23:29:19 -0700 x86: avoid remapping data in parse_setup_data() Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, remap the setup_data header and allow parsing functions for individual types to handle their own data remapping. Signed-off-by: Linn Crosetto Link: http://lkml.kernel.org/r/1376430401-67445-1-git-send-email-l...@hp.com Acked-by: Yinghai Lu Reviewed-by: Pekka Enberg Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/e820.h | 2 +- arch/x86/kernel/e820.c | 5 - arch/x86/kernel/setup.c | 19 --- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index cccd07f..779c2ef 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -29,7 +29,7 @@ extern void e820_setup_gap(void); extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, unsigned long start_addr, unsigned long long end_addr); struct setup_data; -extern void parse_e820_ext(struct setup_data *data); +extern void parse_e820_ext(u64 phys_addr, u32 data_len); #if defined(CONFIG_X86_64) || \ (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d32abea..174da5f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -658,15 +658,18 @@ __init void e820_setup_gap(void) * boot_params.e820_map, others are passed via SETUP_E820_EXT node of * linked list of struct setup_data, which is parsed here. */ -void __init parse_e820_ext(struct setup_data *sdata) +void __init parse_e820_ext(u64 phys_addr, u32 data_len) { int entries; struct e820entry *extmap; + struct setup_data *sdata; + sdata = early_memremap(phys_addr, data_len); entries = sdata->len / sizeof(struct e820entry); extmap = (struct e820entry *)(sdata->data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), _map); + early_iounmap(sdata, data_len); printk(KERN_INFO "e820: extended physical RAM map:\n"); e820_print_map("extended"); } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index de33798..b6b45e4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) static void __init parse_setup_data(void) { struct setup_data *data; - u64 pa_data; + u64 pa_data, pa_next; pa_data = boot_params.hdr.setup_data; while (pa_data) { - u32 data_len, map_len; + u32 data_len, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); - if (data_len > map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } + data_type = data->type; + pa_next = data->next; + early_iounmap(data, map_len); - switch (data->type) { + switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) default: break; } - pa_data = data->next; - early_iounmap(data, map_len); + pa_data = pa_next; } } -- 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/
[tip:x86/mm] x86: avoid remapping data in parse_setup_data()
Commit-ID: 30e46b574a1db7d14404e52dca8e1aa5f5155fd2 Gitweb: http://git.kernel.org/tip/30e46b574a1db7d14404e52dca8e1aa5f5155fd2 Author: Linn Crosetto l...@hp.com AuthorDate: Tue, 13 Aug 2013 15:46:41 -0600 Committer: H. Peter Anvin h...@linux.intel.com CommitDate: Tue, 13 Aug 2013 23:29:19 -0700 x86: avoid remapping data in parse_setup_data() Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, remap the setup_data header and allow parsing functions for individual types to handle their own data remapping. Signed-off-by: Linn Crosetto l...@hp.com Link: http://lkml.kernel.org/r/1376430401-67445-1-git-send-email-l...@hp.com Acked-by: Yinghai Lu ying...@kernel.org Reviewed-by: Pekka Enberg penb...@kernel.org Signed-off-by: H. Peter Anvin h...@linux.intel.com --- arch/x86/include/asm/e820.h | 2 +- arch/x86/kernel/e820.c | 5 - arch/x86/kernel/setup.c | 19 --- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index cccd07f..779c2ef 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -29,7 +29,7 @@ extern void e820_setup_gap(void); extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, unsigned long start_addr, unsigned long long end_addr); struct setup_data; -extern void parse_e820_ext(struct setup_data *data); +extern void parse_e820_ext(u64 phys_addr, u32 data_len); #if defined(CONFIG_X86_64) || \ (defined(CONFIG_X86_32) defined(CONFIG_HIBERNATION)) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d32abea..174da5f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -658,15 +658,18 @@ __init void e820_setup_gap(void) * boot_params.e820_map, others are passed via SETUP_E820_EXT node of * linked list of struct setup_data, which is parsed here. */ -void __init parse_e820_ext(struct setup_data *sdata) +void __init parse_e820_ext(u64 phys_addr, u32 data_len) { int entries; struct e820entry *extmap; + struct setup_data *sdata; + sdata = early_memremap(phys_addr, data_len); entries = sdata-len / sizeof(struct e820entry); extmap = (struct e820entry *)(sdata-data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), e820.nr_map); + early_iounmap(sdata, data_len); printk(KERN_INFO e820: extended physical RAM map:\n); e820_print_map(extended); } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index de33798..b6b45e4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) static void __init parse_setup_data(void) { struct setup_data *data; - u64 pa_data; + u64 pa_data, pa_next; pa_data = boot_params.hdr.setup_data; while (pa_data) { - u32 data_len, map_len; + u32 data_len, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data-len + sizeof(struct setup_data); - if (data_len map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } + data_type = data-type; + pa_next = data-next; + early_iounmap(data, map_len); - switch (data-type) { + switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) default: break; } - pa_data = data-next; - early_iounmap(data, map_len); + pa_data = pa_next; } } -- 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/
[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 --- arch/x86/boot/compressed/eboot.c | 220 --- 1 file changed, 157 insertions(+), 63 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..89fcfe6 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,20 +982,158 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext->type = SETUP_E820_EXT; + e820ext->len = nr_entries * sizeof(struct e820entry); + e820ext->next = 0; + + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; + + while (data && data->next) + data = (struct setup_data *)(unsigned long)data->next; + + if (data) + data->next = (unsigned long)e820ext; + else + params->hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = >e820_map[0]; + struct efi_info *efi = >efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size; + + for (i = 0; i < nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi->efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); + switch (d->type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev && prev->type == e820_type && + (prev->addr + prev->size) == d->phys_addr) { + prev->size += d->num_pages << 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params->e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size < need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext->data; + } + + e820_map->addr = d->phys_addr; + e820_map->size = d->num_pages << PAGE_SHIFT; + e820_map->type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries > ARRAY_SIZE(params->e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params->e820_entries = (u8)nr_entries; + + return EFI_SUCCESS; +} + +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, + u32 *e820ext_size) +{ + efi_st
[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 l...@hp.com --- arch/x86/boot/compressed/eboot.c | 220 --- 1 file changed, 157 insertions(+), 63 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..89fcfe6 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -982,20 +982,158 @@ fail: return NULL; } +static void add_e820ext(struct boot_params *params, + struct setup_data *e820ext, u32 nr_entries) +{ + struct setup_data *data; + efi_status_t status; + unsigned long size; + + e820ext-type = SETUP_E820_EXT; + e820ext-len = nr_entries * sizeof(struct e820entry); + e820ext-next = 0; + + data = (struct setup_data *)(unsigned long)params-hdr.setup_data; + + while (data data-next) + data = (struct setup_data *)(unsigned long)data-next; + + if (data) + data-next = (unsigned long)e820ext; + else + params-hdr.setup_data = (unsigned long)e820ext; +} + +static efi_status_t setup_e820(struct boot_params *params, + struct setup_data *e820ext, u32 e820ext_size) +{ + struct e820entry *e820_map = params-e820_map[0]; + struct efi_info *efi = params-efi_info; + struct e820entry *prev = NULL; + u32 nr_entries; + u32 nr_desc; + int i; + + nr_entries = 0; + nr_desc = efi-efi_memmap_size / efi-efi_memdesc_size; + + for (i = 0; i nr_desc; i++) { + efi_memory_desc_t *d; + unsigned int e820_type = 0; + unsigned long m = efi-efi_memmap; + + d = (efi_memory_desc_t *)(m + (i * efi-efi_memdesc_size)); + switch (d-type) { + case EFI_RESERVED_TYPE: + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + e820_type = E820_RESERVED; + break; + + case EFI_UNUSABLE_MEMORY: + e820_type = E820_UNUSABLE; + break; + + case EFI_ACPI_RECLAIM_MEMORY: + e820_type = E820_ACPI; + break; + + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + e820_type = E820_RAM; + break; + + case EFI_ACPI_MEMORY_NVS: + e820_type = E820_NVS; + break; + + default: + continue; + } + + /* Merge adjacent mappings */ + if (prev prev-type == e820_type + (prev-addr + prev-size) == d-phys_addr) { + prev-size += d-num_pages 12; + continue; + } + + if (nr_entries == ARRAY_SIZE(params-e820_map)) { + u32 need = (nr_desc - i) * sizeof(struct e820entry) + + sizeof(struct setup_data); + + if (!e820ext || e820ext_size need) + return EFI_BUFFER_TOO_SMALL; + + /* boot_params map full, switch to e820 extended */ + e820_map = (struct e820entry *)e820ext-data; + } + + e820_map-addr = d-phys_addr; + e820_map-size = d-num_pages PAGE_SHIFT; + e820_map-type = e820_type; + prev = e820_map++; + nr_entries++; + } + + if (nr_entries ARRAY_SIZE(params-e820_map)) { + u32 nr_e820ext = nr_entries - ARRAY_SIZE(params-e820_map); + + add_e820ext(params, e820ext, nr_e820ext); + nr_entries -= nr_e820ext; + } + + params-e820_entries = (u8)nr_entries; + + return EFI_SUCCESS; +} + +static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, + u32 *e820ext_size) +{ + efi_status_t status; + unsigned long size; + + size = sizeof(struct setup_data) + + sizeof(struct e820entry) * nr_desc; + + if (*e820ext
Re: [RFC PATCH 0/4] EFI boot stub memory map fix
On Mon, Aug 19, 2013 at 01:47:41PM -0700, Yinghai Lu wrote: > On Mon, Aug 19, 2013 at 1:06 PM, H. Peter Anvin wrote: > > I would strongly disagree that option 2 is the cleaner solution. > > Agreed. > > > > > Linn Crosetto wrote: > >>I realize the EFI stub for ARM patches are in flight, > >> > >>https://lkml.org/lkml/2013/8/9/554 > >> > >>and overlap with some of the files but I wanted to send these out for > >>comment. > >> > >>This series fixes a problem with EFI memory maps larger than 128 > >>entries when > >>booting using the EFI boot stub, which results in overflowing the > >>e820_map in > >>boot_params and an eventual halt when checking the map size in > >>sanitize_e820_map(). > >> > >>The fix implemented is to add the EFI memory map from setup_arch() via > >>a > >>memory_setup hook. > >> > >>Two options were considered: > >> > >> 1. Use the SETUP_E820_EXT setup_data type to add the extra entries. > >> > >>2. Create a memory_setup function to be enabled when the EFI memory map > >>is > >>needed. > >> > >>Option 2 appeared to be the cleaner solution, reducing duplication with > >>existing code, given a reasonable mechanism for determining when to > >>replace the default memory_setup function. > > If boot_loader could create setup_data with SETUP_E820_EXT, > efi_stub should go that path too. > We should not add another path. My consideration was in leveraging do_add_efi_memmap(), which duplicates what is done with the map in exit_boot(), and can already be called via the "add_efi_memmap" parameter. One complication with SETUP_E820_EXT is in determining the size needed, since a call to allocate_pool will change the memory map. I will send another version which uses SETUP_E820_EXT. Thanks, Linn -- 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/
[RFC PATCH 3/4] efi: Add efi_memmap_needed()
The function efi_memmap_needed() is used to determine when to use the EFI memory map during boot instead of a BIOS provided e820. The intent is to determine whether we are booted on an EFI system from the EFI boot stub (came in through efi_main(), implemented by checking efi_is_native() and the boot loader identifier), and that there is no e820 map already provided. Signed-off-by: Linn Crosetto --- arch/x86/platform/efi/efi.c | 7 +++ include/linux/efi.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index c2a660c..af32a21 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -719,6 +719,13 @@ char * __init efi_memory_setup(void) return who; } +int __init efi_memmap_needed(void) +{ + return efi_is_native() && + boot_params.e820_entries == 0 && + boot_params.hdr.type_of_loader >> 4 == 2; /* bootsect-loader */ +} + void __init efi_init(void) { efi_char16_t *c16; diff --git a/include/linux/efi.h b/include/linux/efi.h index 977bbc7..95b2251 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -567,6 +567,7 @@ efi_guid_unparse(efi_guid_t *guid, char *out) return out; } +extern int efi_memmap_needed(void); extern char *efi_memory_setup(void); extern void efi_init (void); extern void *efi_get_pal_addr (void); -- 1.7.11.3 -- 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/
[RFC PATCH 4/4] x86: Fix EFI boot stub for large memory maps
This patch adds support for EFI memory maps larger than 128 entries when booted using the EFI boot stub. The e820 map in struct boot_params can only hold 128 entries, but the memory map provided by EFI may be larger. If the map contained more than 128 entries, exit_boot() would write beyond the e820_map array in boot_params and the system would eventually halt in the BUG_ON check in sanitize_e820_map(). In the case we come in through efi_main(), the EFI memory map is used. Instead of populating e820_map in boot_params, create the e820 from the EFI memory map in setup_arch() via a memory_setup hook. The EFI memory map may also be added in efi_init() if the command line parameter "add_efi_memmap" is specified. This is left intact to allow the command line parameter to remain effective. Signed-off-by: Linn Crosetto --- arch/x86/boot/compressed/eboot.c | 64 ++-- arch/x86/kernel/setup.c | 3 ++ 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..66b8d3d 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -973,6 +973,9 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) if (status != EFI_SUCCESS) goto fail2; + /* Use EFI memory map */ + boot_params->e820_entries = 0; + return boot_params; fail2: if (options_size) @@ -986,8 +989,6 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) { struct efi_info *efi = _params->efi_info; - struct e820entry *e820_map = _params->e820_map[0]; - struct e820entry *prev = NULL; unsigned long size, key, desc_size, _size; efi_memory_desc_t *mem_map; efi_status_t status; @@ -1049,65 +1050,6 @@ get_map: /* Historic? */ boot_params->alt_mem_k = 32 * 1024; - /* -* Convert the EFI memory map to E820. -*/ - nr_entries = 0; - for (i = 0; i < size / desc_size; i++) { - efi_memory_desc_t *d; - unsigned int e820_type = 0; - unsigned long m = (unsigned long)mem_map; - - d = (efi_memory_desc_t *)(m + (i * desc_size)); - switch (d->type) { - case EFI_RESERVED_TYPE: - case EFI_RUNTIME_SERVICES_CODE: - case EFI_RUNTIME_SERVICES_DATA: - case EFI_MEMORY_MAPPED_IO: - case EFI_MEMORY_MAPPED_IO_PORT_SPACE: - case EFI_PAL_CODE: - e820_type = E820_RESERVED; - break; - - case EFI_UNUSABLE_MEMORY: - e820_type = E820_UNUSABLE; - break; - - case EFI_ACPI_RECLAIM_MEMORY: - e820_type = E820_ACPI; - break; - - case EFI_LOADER_CODE: - case EFI_LOADER_DATA: - case EFI_BOOT_SERVICES_CODE: - case EFI_BOOT_SERVICES_DATA: - case EFI_CONVENTIONAL_MEMORY: - e820_type = E820_RAM; - break; - - case EFI_ACPI_MEMORY_NVS: - e820_type = E820_NVS; - break; - - default: - continue; - } - - /* Merge adjacent mappings */ - if (prev && prev->type == e820_type && - (prev->addr + prev->size) == d->phys_addr) - prev->size += d->num_pages << 12; - else { - e820_map->addr = d->phys_addr; - e820_map->size = d->num_pages << 12; - e820_map->type = e820_type; - prev = e820_map++; - nr_entries++; - } - } - - boot_params->e820_entries = nr_entries; - return EFI_SUCCESS; free_mem_map: diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..9682c8c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -920,6 +920,9 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled(EFI_BOOT)) efi_memblock_x86_reserve_range(); + + if (efi_memmap_needed()) + x86_init.resources.memory_setup = efi_memory_setup; #endif x86_init.oem.arch_setup(); -- 1.7.11.3 -- 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/
[RFC PATCH 0/4] EFI boot stub memory map fix
I realize the EFI stub for ARM patches are in flight, https://lkml.org/lkml/2013/8/9/554 and overlap with some of the files but I wanted to send these out for comment. This series fixes a problem with EFI memory maps larger than 128 entries when booting using the EFI boot stub, which results in overflowing the e820_map in boot_params and an eventual halt when checking the map size in sanitize_e820_map(). The fix implemented is to add the EFI memory map from setup_arch() via a memory_setup hook. Two options were considered: 1. Use the SETUP_E820_EXT setup_data type to add the extra entries. 2. Create a memory_setup function to be enabled when the EFI memory map is needed. Option 2 appeared to be the cleaner solution, reducing duplication with existing code, given a reasonable mechanism for determining when to replace the default memory_setup function. Linn Crosetto (4): efi: Decouple efi_memmap_init() and do_add_efi_memmap() efi: Add memory_setup function efi_memory_setup() efi: Add efi_memmap_needed() x86: Fix EFI boot stub for large memory maps arch/x86/boot/compressed/eboot.c | 64 ++-- arch/x86/kernel/setup.c | 3 ++ arch/x86/platform/efi/efi.c | 51 +++- include/linux/efi.h | 2 ++ 4 files changed, 45 insertions(+), 75 deletions(-) -- 1.7.11.3 -- 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/
[RFC PATCH 1/4] efi: Decouple efi_memmap_init() and do_add_efi_memmap()
In order to enable the EFI memory map to be initialized outside of efi_init(), decouple the two functions efi_memmap_init() and do_add_efi_memmap() and set the x86_facility EFI_MEMMAP in efi_memmap_init(). Additionally, check EFI_MEMMAP to determine whether efi_memmap_init() has been previously called to avoid doing the initialization more than once. Signed-off-by: Linn Crosetto --- arch/x86/platform/efi/efi.c | 44 ++-- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed1..32da922 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -326,6 +326,24 @@ void efi_get_time(struct timespec *now) now->tv_nsec = 0; } +static int __init efi_memmap_init(void) +{ + if (efi_enabled(EFI_MEMMAP)) + return 0; /* already initialized */ + + /* Map the EFI memory map */ + memmap.map = early_ioremap((unsigned long)memmap.phys_map, + memmap.nr_map * memmap.desc_size); + if (memmap.map == NULL) { + pr_err("Could not map the memory map!\n"); + return -ENOMEM; + } + memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + + set_bit(EFI_MEMMAP, _efi_facility); + return 0; +} + /* * Tell the kernel about the EFI memory map. This might include * more than the max 128 entries that can fit in the e820 legacy @@ -336,6 +354,9 @@ static void __init do_add_efi_memmap(void) { void *p; + if (!efi_enabled(EFI_MEMMAP) && efi_memmap_init()) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -409,6 +430,9 @@ static void __init print_efi_memmap(void) void *p; int i; + if (!efi_enabled(EFI_MEMMAP)) + return; + for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) { @@ -687,23 +711,6 @@ static int __init efi_runtime_init(void) return 0; } -static int __init efi_memmap_init(void) -{ - /* Map the EFI memory map */ - memmap.map = early_ioremap((unsigned long)memmap.phys_map, - memmap.nr_map * memmap.desc_size); - if (memmap.map == NULL) { - pr_err("Could not map the memory map!\n"); - return -ENOMEM; - } - memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); - - if (add_efi_memmap) - do_add_efi_memmap(); - - return 0; -} - void __init efi_init(void) { efi_char16_t *c16; @@ -766,7 +773,8 @@ void __init efi_init(void) if (efi_memmap_init()) return; - set_bit(EFI_MEMMAP, _efi_facility); + if (add_efi_memmap) + do_add_efi_memmap(); #ifdef CONFIG_X86_32 if (efi_is_native()) { -- 1.7.11.3 -- 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/
[RFC PATCH 2/4] efi: Add memory_setup function efi_memory_setup()
Adding efi_memory_setup() to be used to override the default memory_setup function when the EFI memory map should be used instead of a BIOS provided e820 map. Signed-off-by: Linn Crosetto --- arch/x86/platform/efi/efi.c | 8 include/linux/efi.h | 1 + 2 files changed, 9 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 32da922..c2a660c 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -711,6 +711,14 @@ static int __init efi_runtime_init(void) return 0; } +char * __init efi_memory_setup(void) +{ + char *who = "EFI"; + efi_memmap_init(); + do_add_efi_memmap(); + return who; +} + void __init efi_init(void) { efi_char16_t *c16; diff --git a/include/linux/efi.h b/include/linux/efi.h index 5f8f176..977bbc7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -567,6 +567,7 @@ efi_guid_unparse(efi_guid_t *guid, char *out) return out; } +extern char *efi_memory_setup(void); extern void efi_init (void); extern void *efi_get_pal_addr (void); extern void efi_map_pal_code (void); -- 1.7.11.3 -- 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/
[RFC PATCH 2/4] efi: Add memory_setup function efi_memory_setup()
Adding efi_memory_setup() to be used to override the default memory_setup function when the EFI memory map should be used instead of a BIOS provided e820 map. Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/platform/efi/efi.c | 8 include/linux/efi.h | 1 + 2 files changed, 9 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 32da922..c2a660c 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -711,6 +711,14 @@ static int __init efi_runtime_init(void) return 0; } +char * __init efi_memory_setup(void) +{ + char *who = EFI; + efi_memmap_init(); + do_add_efi_memmap(); + return who; +} + void __init efi_init(void) { efi_char16_t *c16; diff --git a/include/linux/efi.h b/include/linux/efi.h index 5f8f176..977bbc7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -567,6 +567,7 @@ efi_guid_unparse(efi_guid_t *guid, char *out) return out; } +extern char *efi_memory_setup(void); extern void efi_init (void); extern void *efi_get_pal_addr (void); extern void efi_map_pal_code (void); -- 1.7.11.3 -- 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/
[RFC PATCH 1/4] efi: Decouple efi_memmap_init() and do_add_efi_memmap()
In order to enable the EFI memory map to be initialized outside of efi_init(), decouple the two functions efi_memmap_init() and do_add_efi_memmap() and set the x86_facility EFI_MEMMAP in efi_memmap_init(). Additionally, check EFI_MEMMAP to determine whether efi_memmap_init() has been previously called to avoid doing the initialization more than once. Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/platform/efi/efi.c | 44 ++-- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed1..32da922 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -326,6 +326,24 @@ void efi_get_time(struct timespec *now) now-tv_nsec = 0; } +static int __init efi_memmap_init(void) +{ + if (efi_enabled(EFI_MEMMAP)) + return 0; /* already initialized */ + + /* Map the EFI memory map */ + memmap.map = early_ioremap((unsigned long)memmap.phys_map, + memmap.nr_map * memmap.desc_size); + if (memmap.map == NULL) { + pr_err(Could not map the memory map!\n); + return -ENOMEM; + } + memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + + set_bit(EFI_MEMMAP, x86_efi_facility); + return 0; +} + /* * Tell the kernel about the EFI memory map. This might include * more than the max 128 entries that can fit in the e820 legacy @@ -336,6 +354,9 @@ static void __init do_add_efi_memmap(void) { void *p; + if (!efi_enabled(EFI_MEMMAP) efi_memmap_init()) + return; + for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md-phys_addr; @@ -409,6 +430,9 @@ static void __init print_efi_memmap(void) void *p; int i; + if (!efi_enabled(EFI_MEMMAP)) + return; + for (p = memmap.map, i = 0; p memmap.map_end; p += memmap.desc_size, i++) { @@ -687,23 +711,6 @@ static int __init efi_runtime_init(void) return 0; } -static int __init efi_memmap_init(void) -{ - /* Map the EFI memory map */ - memmap.map = early_ioremap((unsigned long)memmap.phys_map, - memmap.nr_map * memmap.desc_size); - if (memmap.map == NULL) { - pr_err(Could not map the memory map!\n); - return -ENOMEM; - } - memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); - - if (add_efi_memmap) - do_add_efi_memmap(); - - return 0; -} - void __init efi_init(void) { efi_char16_t *c16; @@ -766,7 +773,8 @@ void __init efi_init(void) if (efi_memmap_init()) return; - set_bit(EFI_MEMMAP, x86_efi_facility); + if (add_efi_memmap) + do_add_efi_memmap(); #ifdef CONFIG_X86_32 if (efi_is_native()) { -- 1.7.11.3 -- 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/
[RFC PATCH 0/4] EFI boot stub memory map fix
I realize the EFI stub for ARM patches are in flight, https://lkml.org/lkml/2013/8/9/554 and overlap with some of the files but I wanted to send these out for comment. This series fixes a problem with EFI memory maps larger than 128 entries when booting using the EFI boot stub, which results in overflowing the e820_map in boot_params and an eventual halt when checking the map size in sanitize_e820_map(). The fix implemented is to add the EFI memory map from setup_arch() via a memory_setup hook. Two options were considered: 1. Use the SETUP_E820_EXT setup_data type to add the extra entries. 2. Create a memory_setup function to be enabled when the EFI memory map is needed. Option 2 appeared to be the cleaner solution, reducing duplication with existing code, given a reasonable mechanism for determining when to replace the default memory_setup function. Linn Crosetto (4): efi: Decouple efi_memmap_init() and do_add_efi_memmap() efi: Add memory_setup function efi_memory_setup() efi: Add efi_memmap_needed() x86: Fix EFI boot stub for large memory maps arch/x86/boot/compressed/eboot.c | 64 ++-- arch/x86/kernel/setup.c | 3 ++ arch/x86/platform/efi/efi.c | 51 +++- include/linux/efi.h | 2 ++ 4 files changed, 45 insertions(+), 75 deletions(-) -- 1.7.11.3 -- 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/
[RFC PATCH 4/4] x86: Fix EFI boot stub for large memory maps
This patch adds support for EFI memory maps larger than 128 entries when booted using the EFI boot stub. The e820 map in struct boot_params can only hold 128 entries, but the memory map provided by EFI may be larger. If the map contained more than 128 entries, exit_boot() would write beyond the e820_map array in boot_params and the system would eventually halt in the BUG_ON check in sanitize_e820_map(). In the case we come in through efi_main(), the EFI memory map is used. Instead of populating e820_map in boot_params, create the e820 from the EFI memory map in setup_arch() via a memory_setup hook. The EFI memory map may also be added in efi_init() if the command line parameter add_efi_memmap is specified. This is left intact to allow the command line parameter to remain effective. Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/boot/compressed/eboot.c | 64 ++-- arch/x86/kernel/setup.c | 3 ++ 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a4..66b8d3d 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -973,6 +973,9 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) if (status != EFI_SUCCESS) goto fail2; + /* Use EFI memory map */ + boot_params-e820_entries = 0; + return boot_params; fail2: if (options_size) @@ -986,8 +989,6 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) { 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; efi_status_t status; @@ -1049,65 +1050,6 @@ get_map: /* Historic? */ boot_params-alt_mem_k = 32 * 1024; - /* -* Convert the EFI memory map to E820. -*/ - nr_entries = 0; - for (i = 0; i size / desc_size; i++) { - efi_memory_desc_t *d; - unsigned int e820_type = 0; - unsigned long m = (unsigned long)mem_map; - - d = (efi_memory_desc_t *)(m + (i * desc_size)); - switch (d-type) { - case EFI_RESERVED_TYPE: - case EFI_RUNTIME_SERVICES_CODE: - case EFI_RUNTIME_SERVICES_DATA: - case EFI_MEMORY_MAPPED_IO: - case EFI_MEMORY_MAPPED_IO_PORT_SPACE: - case EFI_PAL_CODE: - e820_type = E820_RESERVED; - break; - - case EFI_UNUSABLE_MEMORY: - e820_type = E820_UNUSABLE; - break; - - case EFI_ACPI_RECLAIM_MEMORY: - e820_type = E820_ACPI; - break; - - case EFI_LOADER_CODE: - case EFI_LOADER_DATA: - case EFI_BOOT_SERVICES_CODE: - case EFI_BOOT_SERVICES_DATA: - case EFI_CONVENTIONAL_MEMORY: - e820_type = E820_RAM; - break; - - case EFI_ACPI_MEMORY_NVS: - e820_type = E820_NVS; - break; - - default: - continue; - } - - /* Merge adjacent mappings */ - if (prev prev-type == e820_type - (prev-addr + prev-size) == d-phys_addr) - prev-size += d-num_pages 12; - else { - e820_map-addr = d-phys_addr; - e820_map-size = d-num_pages 12; - e820_map-type = e820_type; - prev = e820_map++; - nr_entries++; - } - } - - boot_params-e820_entries = nr_entries; - return EFI_SUCCESS; free_mem_map: diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..9682c8c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -920,6 +920,9 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled(EFI_BOOT)) efi_memblock_x86_reserve_range(); + + if (efi_memmap_needed()) + x86_init.resources.memory_setup = efi_memory_setup; #endif x86_init.oem.arch_setup(); -- 1.7.11.3 -- 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/
[RFC PATCH 3/4] efi: Add efi_memmap_needed()
The function efi_memmap_needed() is used to determine when to use the EFI memory map during boot instead of a BIOS provided e820. The intent is to determine whether we are booted on an EFI system from the EFI boot stub (came in through efi_main(), implemented by checking efi_is_native() and the boot loader identifier), and that there is no e820 map already provided. Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/platform/efi/efi.c | 7 +++ include/linux/efi.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index c2a660c..af32a21 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -719,6 +719,13 @@ char * __init efi_memory_setup(void) return who; } +int __init efi_memmap_needed(void) +{ + return efi_is_native() + boot_params.e820_entries == 0 + boot_params.hdr.type_of_loader 4 == 2; /* bootsect-loader */ +} + void __init efi_init(void) { efi_char16_t *c16; diff --git a/include/linux/efi.h b/include/linux/efi.h index 977bbc7..95b2251 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -567,6 +567,7 @@ efi_guid_unparse(efi_guid_t *guid, char *out) return out; } +extern int efi_memmap_needed(void); extern char *efi_memory_setup(void); extern void efi_init (void); extern void *efi_get_pal_addr (void); -- 1.7.11.3 -- 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: [RFC PATCH 0/4] EFI boot stub memory map fix
On Mon, Aug 19, 2013 at 01:47:41PM -0700, Yinghai Lu wrote: On Mon, Aug 19, 2013 at 1:06 PM, H. Peter Anvin h...@zytor.com wrote: I would strongly disagree that option 2 is the cleaner solution. Agreed. Linn Crosetto l...@hp.com wrote: I realize the EFI stub for ARM patches are in flight, https://lkml.org/lkml/2013/8/9/554 and overlap with some of the files but I wanted to send these out for comment. This series fixes a problem with EFI memory maps larger than 128 entries when booting using the EFI boot stub, which results in overflowing the e820_map in boot_params and an eventual halt when checking the map size in sanitize_e820_map(). The fix implemented is to add the EFI memory map from setup_arch() via a memory_setup hook. Two options were considered: 1. Use the SETUP_E820_EXT setup_data type to add the extra entries. 2. Create a memory_setup function to be enabled when the EFI memory map is needed. Option 2 appeared to be the cleaner solution, reducing duplication with existing code, given a reasonable mechanism for determining when to replace the default memory_setup function. If boot_loader could create setup_data with SETUP_E820_EXT, efi_stub should go that path too. We should not add another path. My consideration was in leveraging do_add_efi_memmap(), which duplicates what is done with the map in exit_boot(), and can already be called via the add_efi_memmap parameter. One complication with SETUP_E820_EXT is in determining the size needed, since a call to allocate_pool will change the memory map. I will send another version which uses SETUP_E820_EXT. Thanks, Linn -- 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/
[PATCH v3] x86: avoid remapping data in parse_setup_data()
Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, remap the setup_data header and allow parsing functions for individual types to handle their own data remapping. Signed-off-by: Linn Crosetto --- v3: Remove data remapping code from parse_setup_data() and add it to parse_e820_ext(). arch/x86/include/asm/e820.h | 2 +- arch/x86/kernel/e820.c | 5 - arch/x86/kernel/setup.c | 19 --- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index cccd07f..779c2ef 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -29,7 +29,7 @@ extern void e820_setup_gap(void); extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, unsigned long start_addr, unsigned long long end_addr); struct setup_data; -extern void parse_e820_ext(struct setup_data *data); +extern void parse_e820_ext(u64 phys_addr, u32 data_len); #if defined(CONFIG_X86_64) || \ (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d32abea..174da5f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -658,15 +658,18 @@ __init void e820_setup_gap(void) * boot_params.e820_map, others are passed via SETUP_E820_EXT node of * linked list of struct setup_data, which is parsed here. */ -void __init parse_e820_ext(struct setup_data *sdata) +void __init parse_e820_ext(u64 phys_addr, u32 data_len) { int entries; struct e820entry *extmap; + struct setup_data *sdata; + sdata = early_memremap(phys_addr, data_len); entries = sdata->len / sizeof(struct e820entry); extmap = (struct e820entry *)(sdata->data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), _map); + early_iounmap(sdata, data_len); printk(KERN_INFO "e820: extended physical RAM map:\n"); e820_print_map("extended"); } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..234e1e3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) static void __init parse_setup_data(void) { struct setup_data *data; - u64 pa_data; + u64 pa_data, pa_next; pa_data = boot_params.hdr.setup_data; while (pa_data) { - u32 data_len, map_len; + u32 data_len, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); - if (data_len > map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } + data_type = data->type; + pa_next = data->next; + early_iounmap(data, map_len); - switch (data->type) { + switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) default: break; } - pa_data = data->next; - early_iounmap(data, map_len); + pa_data = pa_next; } } -- 1.7.11.3 -- 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/
[PATCH v3] x86: avoid remapping data in parse_setup_data()
Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, remap the setup_data header and allow parsing functions for individual types to handle their own data remapping. Signed-off-by: Linn Crosetto l...@hp.com --- v3: Remove data remapping code from parse_setup_data() and add it to parse_e820_ext(). arch/x86/include/asm/e820.h | 2 +- arch/x86/kernel/e820.c | 5 - arch/x86/kernel/setup.c | 19 --- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index cccd07f..779c2ef 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -29,7 +29,7 @@ extern void e820_setup_gap(void); extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, unsigned long start_addr, unsigned long long end_addr); struct setup_data; -extern void parse_e820_ext(struct setup_data *data); +extern void parse_e820_ext(u64 phys_addr, u32 data_len); #if defined(CONFIG_X86_64) || \ (defined(CONFIG_X86_32) defined(CONFIG_HIBERNATION)) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d32abea..174da5f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -658,15 +658,18 @@ __init void e820_setup_gap(void) * boot_params.e820_map, others are passed via SETUP_E820_EXT node of * linked list of struct setup_data, which is parsed here. */ -void __init parse_e820_ext(struct setup_data *sdata) +void __init parse_e820_ext(u64 phys_addr, u32 data_len) { int entries; struct e820entry *extmap; + struct setup_data *sdata; + sdata = early_memremap(phys_addr, data_len); entries = sdata-len / sizeof(struct e820entry); extmap = (struct e820entry *)(sdata-data); __append_e820_map(extmap, entries); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), e820.nr_map); + early_iounmap(sdata, data_len); printk(KERN_INFO e820: extended physical RAM map:\n); e820_print_map(extended); } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..234e1e3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) static void __init parse_setup_data(void) { struct setup_data *data; - u64 pa_data; + u64 pa_data, pa_next; pa_data = boot_params.hdr.setup_data; while (pa_data) { - u32 data_len, map_len; + u32 data_len, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data-len + sizeof(struct setup_data); - if (data_len map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } + data_type = data-type; + pa_next = data-next; + early_iounmap(data, map_len); - switch (data-type) { + switch (data_type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) default: break; } - pa_data = data-next; - early_iounmap(data, map_len); + pa_data = pa_next; } } -- 1.7.11.3 -- 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/
[PATCH v2] x86: selective remapping in parse_setup_data()
Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, first remap the setup_data header, and remap the data only for types actually parsed in parse_setup_data(). Type SETUP_PCI is handled later by pcibios_add_device(), when ioremap() is available. Signed-off-by: Linn Crosetto --- v2: add more detail to the explanation as requested by hpa --- arch/x86/kernel/setup.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..2063a49 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -423,6 +423,17 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ +static void __init remap_setup_data(u64 pa_data, u32 data_len, + struct setup_data **data, u32 *map_len) +{ + if (data_len <= *map_len) + return; + + early_iounmap(*data, *map_len); + *data = early_memremap(pa_data, data_len); + *map_len = data_len; +} + static void __init parse_setup_data(void) { struct setup_data *data; @@ -432,18 +443,16 @@ static void __init parse_setup_data(void) while (pa_data) { u32 data_len, map_len; + /* The data length may be too large for early remapping, + remap the data only when needed. */ map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); - if (data_len > map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } switch (data->type) { case SETUP_E820_EXT: + remap_setup_data(pa_data, data_len, , _len); parse_e820_ext(data); break; case SETUP_DTB: -- 1.7.11.3 -- 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/
[PATCH] x86: selective remapping in parse_setup_data()
PCI devices may advertise a ROM size larger than early_memremap() is able to handle. If this occurs it leads to a NULL dereference in parse_setup_data(). Avoid this by remapping the data only when necessary. Signed-off-by: Linn Crosetto --- arch/x86/kernel/setup.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..2063a49 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -423,6 +423,17 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ +static void __init remap_setup_data(u64 pa_data, u32 data_len, + struct setup_data **data, u32 *map_len) +{ + if (data_len <= *map_len) + return; + + early_iounmap(*data, *map_len); + *data = early_memremap(pa_data, data_len); + *map_len = data_len; +} + static void __init parse_setup_data(void) { struct setup_data *data; @@ -432,18 +443,16 @@ static void __init parse_setup_data(void) while (pa_data) { u32 data_len, map_len; + /* The data length may be too large for early remapping, + remap the data only when needed. */ map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); - if (data_len > map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } switch (data->type) { case SETUP_E820_EXT: + remap_setup_data(pa_data, data_len, , _len); parse_e820_ext(data); break; case SETUP_DTB: -- 1.7.11.3 -- 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/
[PATCH] x86: selective remapping in parse_setup_data()
PCI devices may advertise a ROM size larger than early_memremap() is able to handle. If this occurs it leads to a NULL dereference in parse_setup_data(). Avoid this by remapping the data only when necessary. Signed-off-by: Linn Crosetto l...@hp.com --- arch/x86/kernel/setup.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..2063a49 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -423,6 +423,17 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ +static void __init remap_setup_data(u64 pa_data, u32 data_len, + struct setup_data **data, u32 *map_len) +{ + if (data_len = *map_len) + return; + + early_iounmap(*data, *map_len); + *data = early_memremap(pa_data, data_len); + *map_len = data_len; +} + static void __init parse_setup_data(void) { struct setup_data *data; @@ -432,18 +443,16 @@ static void __init parse_setup_data(void) while (pa_data) { u32 data_len, map_len; + /* The data length may be too large for early remapping, + remap the data only when needed. */ map_len = max(PAGE_SIZE - (pa_data ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data-len + sizeof(struct setup_data); - if (data_len map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } switch (data-type) { case SETUP_E820_EXT: + remap_setup_data(pa_data, data_len, data, map_len); parse_e820_ext(data); break; case SETUP_DTB: -- 1.7.11.3 -- 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/
[PATCH v2] x86: selective remapping in parse_setup_data()
Type SETUP_PCI, added by setup_efi_pci(), may advertise a ROM size larger than early_memremap() is able to handle, which is currently limited to 256kB. If this occurs it leads to a NULL dereference in parse_setup_data(). To avoid this, first remap the setup_data header, and remap the data only for types actually parsed in parse_setup_data(). Type SETUP_PCI is handled later by pcibios_add_device(), when ioremap() is available. Signed-off-by: Linn Crosetto l...@hp.com --- v2: add more detail to the explanation as requested by hpa --- arch/x86/kernel/setup.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f8ec578..2063a49 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -423,6 +423,17 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ +static void __init remap_setup_data(u64 pa_data, u32 data_len, + struct setup_data **data, u32 *map_len) +{ + if (data_len = *map_len) + return; + + early_iounmap(*data, *map_len); + *data = early_memremap(pa_data, data_len); + *map_len = data_len; +} + static void __init parse_setup_data(void) { struct setup_data *data; @@ -432,18 +443,16 @@ static void __init parse_setup_data(void) while (pa_data) { u32 data_len, map_len; + /* The data length may be too large for early remapping, + remap the data only when needed. */ map_len = max(PAGE_SIZE - (pa_data ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data-len + sizeof(struct setup_data); - if (data_len map_len) { - early_iounmap(data, map_len); - data = early_memremap(pa_data, data_len); - map_len = data_len; - } switch (data-type) { case SETUP_E820_EXT: + remap_setup_data(pa_data, data_len, data, map_len); parse_e820_ext(data); break; case SETUP_DTB: -- 1.7.11.3 -- 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/
[tip:x86/mm] x86/iommu/dmar: Remove warning for HPET scope type
Commit-ID: 13f72756da86f155898e2c2022f7b3a106c3742e Gitweb: http://git.kernel.org/tip/13f72756da86f155898e2c2022f7b3a106c3742e Author: Linn Crosetto AuthorDate: Tue, 23 Apr 2013 12:26:45 -0600 Committer: Ingo Molnar CommitDate: Wed, 24 Apr 2013 08:45:47 +0200 x86/iommu/dmar: Remove warning for HPET scope type ACPI_DMAR_SCOPE_TYPE_HPET is parsed by ir_parse_ioapic_hpet_scope() and should not be flagged as an unsupported type. Signed-off-by: Linn Crosetto Cc: j...@8bytes.org Cc: ddut...@redhat.com Cc: suresh.b.sid...@intel.com Link: http://lkml.kernel.org/r/1366741605-71293-1-git-send-email-l...@hp.com Signed-off-by: Ingo Molnar --- drivers/iommu/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e5cdaf8..b8008f6 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -129,7 +129,8 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; - else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { + else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC && + scope->entry_type != ACPI_DMAR_SCOPE_TYPE_HPET) { pr_warn("Unsupported device scope\n"); } start += scope->length; -- 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/
[tip:x86/mm] x86/iommu/dmar: Remove warning for HPET scope type
Commit-ID: 13f72756da86f155898e2c2022f7b3a106c3742e Gitweb: http://git.kernel.org/tip/13f72756da86f155898e2c2022f7b3a106c3742e Author: Linn Crosetto l...@hp.com AuthorDate: Tue, 23 Apr 2013 12:26:45 -0600 Committer: Ingo Molnar mi...@kernel.org CommitDate: Wed, 24 Apr 2013 08:45:47 +0200 x86/iommu/dmar: Remove warning for HPET scope type ACPI_DMAR_SCOPE_TYPE_HPET is parsed by ir_parse_ioapic_hpet_scope() and should not be flagged as an unsupported type. Signed-off-by: Linn Crosetto l...@hp.com Cc: j...@8bytes.org Cc: ddut...@redhat.com Cc: suresh.b.sid...@intel.com Link: http://lkml.kernel.org/r/1366741605-71293-1-git-send-email-l...@hp.com Signed-off-by: Ingo Molnar mi...@kernel.org --- drivers/iommu/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e5cdaf8..b8008f6 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -129,7 +129,8 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, if (scope-entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope-entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; - else if (scope-entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { + else if (scope-entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC + scope-entry_type != ACPI_DMAR_SCOPE_TYPE_HPET) { pr_warn(Unsupported device scope\n); } start += scope-length; -- 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/
[PATCH] iommu: dmar -- remove warning for HPET scope type
ACPI_DMAR_SCOPE_TYPE_HPET is parsed by ir_parse_ioapic_hpet_scope() and should not be flagged as an unsupported type. Signed-off-by: Linn Crosetto --- drivers/iommu/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e5cdaf8..b8008f6 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -129,7 +129,8 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; - else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { + else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC && + scope->entry_type != ACPI_DMAR_SCOPE_TYPE_HPET) { pr_warn("Unsupported device scope\n"); } start += scope->length; -- 1.7.11.3 -- 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/
[PATCH] iommu: dmar -- remove warning for HPET scope type
ACPI_DMAR_SCOPE_TYPE_HPET is parsed by ir_parse_ioapic_hpet_scope() and should not be flagged as an unsupported type. Signed-off-by: Linn Crosetto l...@hp.com --- drivers/iommu/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e5cdaf8..b8008f6 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -129,7 +129,8 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, if (scope-entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || scope-entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) (*cnt)++; - else if (scope-entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { + else if (scope-entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC + scope-entry_type != ACPI_DMAR_SCOPE_TYPE_HPET) { pr_warn(Unsupported device scope\n); } start += scope-length; -- 1.7.11.3 -- 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: [PATCH] acpi: remove length check for large registers
On Fri, Mar 15, 2013 at 08:50:45PM +, Moore, Robert wrote: > Can you explain in a bit more detail what brings this up? > > I'm aware of the limitation of the generic address structure, but we are > forced by the (current) ACPI specification to use it if it is present for a > given register. A system with a GPE block bit_width of 256 triggers it. In this case, the length check can never succeed. Thanks, Linn -- 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/
[PATCH] acpi: remove length check for large registers
The legacy bit width field in the Generic Address Structure is 1 byte, limiting the reportable register width to 255 bits. Larger registers will cause a length mismatch warning to be printed in acpi_tb_validate_fadt(). To avoid the warning, disable the length mismatch check for registers larger than 255 bits. Signed-off-by: Linn Crosetto --- drivers/acpi/acpica/tbfadt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 74181bf..e87abcd 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -561,6 +561,7 @@ static void acpi_tb_validate_fadt(void) * legacy length field and the corresponding 64-bit X length field. */ if (address64->address && + ACPI_MUL_8(length) <= ACPI_UINT8_MAX && (address64->bit_width != ACPI_MUL_8(length))) { ACPI_BIOS_WARNING((AE_INFO, "32/64X length mismatch in FADT/%s: %u/%u", -- 1.7.11.3 -- 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/
[PATCH] acpi: remove length check for large registers
The legacy bit width field in the Generic Address Structure is 1 byte, limiting the reportable register width to 255 bits. Larger registers will cause a length mismatch warning to be printed in acpi_tb_validate_fadt(). To avoid the warning, disable the length mismatch check for registers larger than 255 bits. Signed-off-by: Linn Crosetto l...@hp.com --- drivers/acpi/acpica/tbfadt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 74181bf..e87abcd 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -561,6 +561,7 @@ static void acpi_tb_validate_fadt(void) * legacy length field and the corresponding 64-bit X length field. */ if (address64-address + ACPI_MUL_8(length) = ACPI_UINT8_MAX (address64-bit_width != ACPI_MUL_8(length))) { ACPI_BIOS_WARNING((AE_INFO, 32/64X length mismatch in FADT/%s: %u/%u, -- 1.7.11.3 -- 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: [PATCH] acpi: remove length check for large registers
On Fri, Mar 15, 2013 at 08:50:45PM +, Moore, Robert wrote: Can you explain in a bit more detail what brings this up? I'm aware of the limitation of the generic address structure, but we are forced by the (current) ACPI specification to use it if it is present for a given register. A system with a GPE block bit_width of 256 triggers it. In this case, the length check can never succeed. Thanks, Linn -- 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/