Re: [PATCH V10 4/5] arm64: apei: implement arch_apei_get_mem_attributes()

From: Ard Biesheuvel
Date: Fri Aug 07 2015 - 05:00:27 EST


On 6 August 2015 at 15:40, Jonathan (Zhixiong) Zhang
<zjzhang@xxxxxxxxxxxxxx> wrote:
> From: "Jonathan (Zhixiong) Zhang" <zjzhang@xxxxxxxxxxxxxx>
>
> Table 8 of UEFI 2.5 section 2.3.6.1 defines mappings from EFI
> memory types to MAIR attribute encodings for arm64.
>
> If the physical address has memory attributes defined by EFI
> memmap as EFI_MEMORY_[UC|WC|WT], return approprate page protection
> type according to the UEFI spec. Otherwise, return PAGE_KERNEL.
>
> Reviewed-by: Catalin Marinas <catalin.marinas@xxxxxxx>
> Acked-by: Hanjun Guo <hanjun.guo@xxxxxxxxxx>
> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@xxxxxxxxxxxxxx>
> ---
> This patch as is does not build on current tip of next branch of
> git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git, a small
> tweak is needed. It builds on tip of linux-next/master of linus'
> repo and origin/master of arm64 repo.
> ---
> arch/arm64/include/asm/acpi.h | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index 1ff9e6eb5e02..1025d0401016 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -19,6 +19,11 @@
> #include <asm/psci.h>
> #include <asm/smp_plat.h>
>
> +#ifdef CONFIG_ACPI_APEI
> +#include <linux/efi.h>
> +#include <asm/pgtable.h>
> +#endif
> +
> /* Macros for consistency checks of the GICC subtable of MADT */
> #define ACPI_MADT_GICC_LENGTH \
> (acpi_gbl_FADT.header.revision < 6 ? 76 : 80)
> @@ -91,4 +95,26 @@ static inline const char *acpi_get_enable_method(int cpu)
> {
> return acpi_psci_present() ? "psci" : NULL;
> }
> +
> +#ifdef CONFIG_ACPI_APEI
> +/*
> + * According to "Table 8 Map: EFI memory types to AArch64 memory types"
> + * of UEFI 2.5 section 2.3.6.1, each EFI memory type is mapped to
> + * corresponding MAIR attribute encoding.
> + */
> +static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
> +{
> + u64 attr;
> +
> + attr = efi_mem_attributes(addr);
> + if (attr & EFI_MEMORY_UC)
> + return __pgprot(PROT_DEVICE_nGnRnE);
> + if (attr & EFI_MEMORY_WC)
> + return __pgprot(PROT_NORMAL_NC);
> + if (attr & EFI_MEMORY_WT)
> + return __pgprot(PROT_NORMAL_WT);
> + return __pgprot(PAGE_KERNEL);

The EFI memory types are not exclusive, and so many regions will have
all of the above set. The UEFI spec does not define how to interpret
these superimposed attributes, it is up to the OS to decide on a
consistent approach.

For instance, this region (captured from a arm64 boot log with
uefi_debug set on the command line)

[Runtime Data |RUN| | | | |WB|WT|WC|UC]

would be mapped uncached when following the above logic, while it
makes more sense to map using PAGE_KERNEL in this case.

>From the spec:

"""
EFI_MEMORY_UC: The memory region supports being configured as not cacheable.
EFI_MEMORY_WC: The memory region supports being configured as write combining.
EFI_MEMORY_WT: The memory region supports being configured as
cacheable with a âwrite throughâ policy. Writes that hit in the cache
will also be written to main memory.
EFI_MEMORY_WB: The memory region supports being configured as
cacheable with a âwrite backâ policy. Reads and writes that hit in the
cache do not propagate to main memory. Dirty data is written back to
main memory when a new cache line is allocated.
"""

Also, the final __pgprot() is redundant here, it is already present in
the definition of PAGE_KERNEL.

--
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/