diff mbox

[v2,04/10] arm64/efi: invert UEFI memory region reservation logic

Message ID 1414513123-20400-5-git-send-email-ard.biesheuvel@linaro.org
State Accepted
Commit 61139eb04056bba69aeef6c481802c4ea028bf4d
Headers show

Commit Message

Ard Biesheuvel Oct. 28, 2014, 4:18 p.m. UTC
Instead of reserving the memory regions based on which types we know
need to be reserved, consider only regions of the following types as
free for general use by the OS:

EFI_LOADER_CODE
EFI_LOADER_DATA
EFI_BOOT_SERVICES_CODE
EFI_BOOT_SERVICES_DATA
EFI_CONVENTIONAL_MEMORY

Note that this also fixes a problem with the original code, which would
misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
perfectly legal for the firmware not to request a virtual mapping for
EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
which case the EFI_MEMORY_RUNTIME attribute would not be set.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/kernel/efi.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Comments

Mark Rutland Oct. 28, 2014, 4:47 p.m. UTC | #1
On Tue, Oct 28, 2014 at 04:18:37PM +0000, Ard Biesheuvel wrote:
> Instead of reserving the memory regions based on which types we know
> need to be reserved, consider only regions of the following types as
> free for general use by the OS:
> 
> EFI_LOADER_CODE
> EFI_LOADER_DATA
> EFI_BOOT_SERVICES_CODE
> EFI_BOOT_SERVICES_DATA
> EFI_CONVENTIONAL_MEMORY
> 
> Note that this also fixes a problem with the original code, which would
> misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
> does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
> perfectly legal for the firmware not to request a virtual mapping for
> EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
> which case the EFI_MEMORY_RUNTIME attribute would not be set.
> 
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  arch/arm64/kernel/efi.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index 95c49ebc660d..2e829148fb36 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -125,17 +125,17 @@ out:
>   */
>  static __init int is_reserve_region(efi_memory_desc_t *md)
>  {
> -	if (!is_normal_ram(md))
> +	switch (md->type) {
> +	case EFI_LOADER_CODE:
> +	case EFI_LOADER_DATA:
> +	case EFI_BOOT_SERVICES_CODE:
> +	case EFI_BOOT_SERVICES_DATA:
> +	case EFI_CONVENTIONAL_MEMORY:
>  		return 0;
> -
> -	if (md->attribute & EFI_MEMORY_RUNTIME)
> -		return 1;
> -
> -	if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
> -	    md->type == EFI_RESERVED_TYPE)
> -		return 1;
> -
> -	return 0;
> +	default:
> +		break;
> +	}
> +	return is_normal_ram(md);

Just to check: did we figure out if UnusableMemory was allowed to have
EFI_MEMORY_WB attributes? If it isn't, this looks fine to me.

If it is, then we will need to remove that memory (rather than reserving
it) to prevent speculative accesses.

Thanks,
Mark.
Ard Biesheuvel Oct. 28, 2014, 5:08 p.m. UTC | #2
On 28 October 2014 17:47, Mark Rutland <mark.rutland@arm.com> wrote:
> On Tue, Oct 28, 2014 at 04:18:37PM +0000, Ard Biesheuvel wrote:
>> Instead of reserving the memory regions based on which types we know
>> need to be reserved, consider only regions of the following types as
>> free for general use by the OS:
>>
>> EFI_LOADER_CODE
>> EFI_LOADER_DATA
>> EFI_BOOT_SERVICES_CODE
>> EFI_BOOT_SERVICES_DATA
>> EFI_CONVENTIONAL_MEMORY
>>
>> Note that this also fixes a problem with the original code, which would
>> misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
>> does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
>> perfectly legal for the firmware not to request a virtual mapping for
>> EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
>> which case the EFI_MEMORY_RUNTIME attribute would not be set.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  arch/arm64/kernel/efi.c | 20 ++++++++++----------
>>  1 file changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
>> index 95c49ebc660d..2e829148fb36 100644
>> --- a/arch/arm64/kernel/efi.c
>> +++ b/arch/arm64/kernel/efi.c
>> @@ -125,17 +125,17 @@ out:
>>   */
>>  static __init int is_reserve_region(efi_memory_desc_t *md)
>>  {
>> -     if (!is_normal_ram(md))
>> +     switch (md->type) {
>> +     case EFI_LOADER_CODE:
>> +     case EFI_LOADER_DATA:
>> +     case EFI_BOOT_SERVICES_CODE:
>> +     case EFI_BOOT_SERVICES_DATA:
>> +     case EFI_CONVENTIONAL_MEMORY:
>>               return 0;
>> -
>> -     if (md->attribute & EFI_MEMORY_RUNTIME)
>> -             return 1;
>> -
>> -     if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
>> -         md->type == EFI_RESERVED_TYPE)
>> -             return 1;
>> -
>> -     return 0;
>> +     default:
>> +             break;
>> +     }
>> +     return is_normal_ram(md);
>
> Just to check: did we figure out if UnusableMemory was allowed to have
> EFI_MEMORY_WB attributes? If it isn't, this looks fine to me.
>
> If it is, then we will need to remove that memory (rather than reserving
> it) to prevent speculative accesses.
>

The spec does not mention at all how EfiUnusableMemory should be used,
and I would assume any such regions to have the EFI_MEMORY_WB
attribute set, as it is carved out of the normal system RAM, and the
way Tianocore/EDK2 implements it at least, all those attributes
(including the write-protect/execute-protect ones) are copied straight
from the underlying regions and never set to reflect the nature of the
actual contents.

However, for 3.20 I intend to propose another change to this code, so
that only non-reserved, usable memory gets memblock_add()'ed in the
first place, and I suppose this should cover your concern as well. The
reason for doing that is to allow tools like dmidecode and lshw access
to the SMBIOS and other tables through /dev/mem, which is currently
disallowed when STRICT_DEVMEM is set.
Mark Rutland Oct. 28, 2014, 5:28 p.m. UTC | #3
On Tue, Oct 28, 2014 at 05:08:29PM +0000, Ard Biesheuvel wrote:
> On 28 October 2014 17:47, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Tue, Oct 28, 2014 at 04:18:37PM +0000, Ard Biesheuvel wrote:
> >> Instead of reserving the memory regions based on which types we know
> >> need to be reserved, consider only regions of the following types as
> >> free for general use by the OS:
> >>
> >> EFI_LOADER_CODE
> >> EFI_LOADER_DATA
> >> EFI_BOOT_SERVICES_CODE
> >> EFI_BOOT_SERVICES_DATA
> >> EFI_CONVENTIONAL_MEMORY
> >>
> >> Note that this also fixes a problem with the original code, which would
> >> misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
> >> does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
> >> perfectly legal for the firmware not to request a virtual mapping for
> >> EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
> >> which case the EFI_MEMORY_RUNTIME attribute would not be set.
> >>
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >>  arch/arm64/kernel/efi.c | 20 ++++++++++----------
> >>  1 file changed, 10 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> >> index 95c49ebc660d..2e829148fb36 100644
> >> --- a/arch/arm64/kernel/efi.c
> >> +++ b/arch/arm64/kernel/efi.c
> >> @@ -125,17 +125,17 @@ out:
> >>   */
> >>  static __init int is_reserve_region(efi_memory_desc_t *md)
> >>  {
> >> -     if (!is_normal_ram(md))
> >> +     switch (md->type) {
> >> +     case EFI_LOADER_CODE:
> >> +     case EFI_LOADER_DATA:
> >> +     case EFI_BOOT_SERVICES_CODE:
> >> +     case EFI_BOOT_SERVICES_DATA:
> >> +     case EFI_CONVENTIONAL_MEMORY:
> >>               return 0;
> >> -
> >> -     if (md->attribute & EFI_MEMORY_RUNTIME)
> >> -             return 1;
> >> -
> >> -     if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
> >> -         md->type == EFI_RESERVED_TYPE)
> >> -             return 1;
> >> -
> >> -     return 0;
> >> +     default:
> >> +             break;
> >> +     }
> >> +     return is_normal_ram(md);
> >
> > Just to check: did we figure out if UnusableMemory was allowed to have
> > EFI_MEMORY_WB attributes? If it isn't, this looks fine to me.
> >
> > If it is, then we will need to remove that memory (rather than reserving
> > it) to prevent speculative accesses.
> >
> 
> The spec does not mention at all how EfiUnusableMemory should be used,
> and I would assume any such regions to have the EFI_MEMORY_WB
> attribute set, as it is carved out of the normal system RAM, and the
> way Tianocore/EDK2 implements it at least, all those attributes
> (including the write-protect/execute-protect ones) are copied straight
> from the underlying regions and never set to reflect the nature of the
> actual contents.

Ok. That's precisely the case I was concerned about.

> However, for 3.20 I intend to propose another change to this code, so
> that only non-reserved, usable memory gets memblock_add()'ed in the
> first place, and I suppose this should cover your concern as well. The
> reason for doing that is to allow tools like dmidecode and lshw access
> to the SMBIOS and other tables through /dev/mem, which is currently
> disallowed when STRICT_DEVMEM is set.

So long as said memory is not later passed to memblock_reserve, that
should be ok for the EfiUnusableMemory case. I guess we haven't actually
seen such memory yet anyhow?

I not all that keen on the usage of /dev/mem for those given the
availability of other interfaces.

Mark.
Roy Franz Oct. 30, 2014, 12:28 a.m. UTC | #4
On Tue, Oct 28, 2014 at 9:18 AM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> Instead of reserving the memory regions based on which types we know
> need to be reserved, consider only regions of the following types as
> free for general use by the OS:
>
> EFI_LOADER_CODE
> EFI_LOADER_DATA
> EFI_BOOT_SERVICES_CODE
> EFI_BOOT_SERVICES_DATA
> EFI_CONVENTIONAL_MEMORY
>
> Note that this also fixes a problem with the original code, which would
> misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
> does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
> perfectly legal for the firmware not to request a virtual mapping for
> EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
> which case the EFI_MEMORY_RUNTIME attribute would not be set.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  arch/arm64/kernel/efi.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index 95c49ebc660d..2e829148fb36 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -125,17 +125,17 @@ out:
>   */
>  static __init int is_reserve_region(efi_memory_desc_t *md)
>  {
> -       if (!is_normal_ram(md))
> +       switch (md->type) {
> +       case EFI_LOADER_CODE:
> +       case EFI_LOADER_DATA:
> +       case EFI_BOOT_SERVICES_CODE:
> +       case EFI_BOOT_SERVICES_DATA:
> +       case EFI_CONVENTIONAL_MEMORY:
>                 return 0;
> -
> -       if (md->attribute & EFI_MEMORY_RUNTIME)
> -               return 1;
> -
> -       if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
> -           md->type == EFI_RESERVED_TYPE)
> -               return 1;
> -
> -       return 0;
> +       default:
> +               break;
> +       }
> +       return is_normal_ram(md);
>  }
>
>  static __init void reserve_regions(void)
> --
> 1.8.3.2
>
Acked-by: Roy Franz <roy.franz@linaro.org>

Looks good, as I expect most new types of memory that are added will
need some special treatment, and shouldn't just
be added to the available general use memory.
diff mbox

Patch

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 95c49ebc660d..2e829148fb36 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -125,17 +125,17 @@  out:
  */
 static __init int is_reserve_region(efi_memory_desc_t *md)
 {
-	if (!is_normal_ram(md))
+	switch (md->type) {
+	case EFI_LOADER_CODE:
+	case EFI_LOADER_DATA:
+	case EFI_BOOT_SERVICES_CODE:
+	case EFI_BOOT_SERVICES_DATA:
+	case EFI_CONVENTIONAL_MEMORY:
 		return 0;
-
-	if (md->attribute & EFI_MEMORY_RUNTIME)
-		return 1;
-
-	if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
-	    md->type == EFI_RESERVED_TYPE)
-		return 1;
-
-	return 0;
+	default:
+		break;
+	}
+	return is_normal_ram(md);
 }
 
 static __init void reserve_regions(void)