[PATCH v1] arm: Support for the PXN CPU feature on ARMv7
Jungseung Lee
js07.lee at gmail.com
Tue Nov 25 08:21:14 PST 2014
Hello catalin,
2014-11-25 0:06 GMT+09:00 Catalin Marinas <catalin.marinas at arm.com>:
> On Sat, Nov 22, 2014 at 10:42:36AM +0000, Jungseung Lee wrote:
>> diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h
>> index 78a7793..e63c633 100644
>> --- a/arch/arm/include/asm/pgalloc.h
>> +++ b/arch/arm/include/asm/pgalloc.h
>> @@ -17,6 +17,7 @@
>> #include <asm/processor.h>
>> #include <asm/cacheflush.h>
>> #include <asm/tlbflush.h>
>> +#include <asm/cputype.h>
>>
>> #define check_pgt_cache() do { } while (0)
>>
>> @@ -25,6 +26,19 @@
>> #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
>> #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
>>
>> +static inline bool cpu_has_classic_pxn(void)
>> +{
>> +#ifdef CONFIG_CPU_V7
>
> I don't think shouldn't trigger this when LPAE is enabled.
>
>> + unsigned int vmsa;
>> +
>> + /* LPAE implies atomic ldrd/strd instructions */
>
> How is this comment relevant? Copy/paste?
>
I am ashamed of the code .. , I will fix that.
>> + vmsa = (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xf) >> 0;
>> + if (vmsa == 4)
>> + return 1;
>> +#endif
>> + return 0;
>> +}
>
> In general we put the #ifdef outside the function:
>
> #if __LINUX_ARM_ARCH__ >= 7 && !defined(CONFIG_ARM_LPAE)
> static inline bool cpu_has_classic_pxn(void)
> {
> unsigned int vmsa = (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xf) >> 0;
> return vmsa == 4;
> }
> #else
> static inline bool cpu_has_classic_pxn(void)
> {
> return false;
> }
> #endif
>
Is it acceptable to use static local variable for storing vmsa?
I think It would be better to check vmsa just one time.
> I used __LINUX_ARM_ARCH__ instead of CONFIG_CPU_V7 to cope with kernel
> images built for both v6 and v7. You could also check for
> cpu_architecture() >= 7, though with a bit of performance impact.
>
>> static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
>> @@ -157,7 +171,11 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
>> static inline void
>> pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
>> {
>> - __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE);
>> + if (cpu_has_classic_pxn())
>> + __pmd_populate(pmdp, page_to_phys(ptep),
>> + _PAGE_USER_TABLE | PMD_PXNTABLE);
>> + else
>> + __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE);
>> }
>
> Nitpick (personal preference):
>
> pmdval_t pmdval = _PAGE_USER_TABLE;
> if (cpu_has_classic_pxn())
> pmdval |= PMD_PXNTABLE;
> __pmd_populate(pmdp, page_to_phys(ptep), pmdval);
>
>> #define pmd_pgtable(pmd) pmd_page(pmd)
>>
>> diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
>> index 5cfba15..5e68278 100644
>> --- a/arch/arm/include/asm/pgtable-2level-hwdef.h
>> +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
>> @@ -20,12 +20,14 @@
>> #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0)
>> #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0)
>> #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0)
>> +#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */
>> #define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
>> #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
>> #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */
>> /*
>> * - section
>> */
>> +#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */
>> #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
>> #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
>> #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */
>> diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h
>> index 9fd61c7..f8f1cff 100644
>> --- a/arch/arm/include/asm/pgtable-3level-hwdef.h
>> +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
>> @@ -76,6 +76,7 @@
>> #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
>> #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */
>> #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */
>> +#define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */
>> #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */
>>
>> /*
>> diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
>> index 3b30062..04db03c 100644
>> --- a/arch/arm/include/asm/pgtable.h
>> +++ b/arch/arm/include/asm/pgtable.h
>> @@ -247,6 +247,9 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
>> if (!pte_special(pteval))
>> __sync_icache_dcache(pteval);
>> ext |= PTE_EXT_NG;
>> +#ifdef CONFIG_ARM_LPAE
>> + ext |= PTE_EXT_PXN;
>> +#endif
>
> I think you can avoid touching set_pte_at() and instead:
>
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 9f98cec7fe1e..5b0a0472e689 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -605,6 +605,11 @@ static void __init build_mem_type_table(void)
> }
> kern_pgprot |= PTE_EXT_AF;
> vecs_pgprot |= PTE_EXT_AF;
> +
> + /*
> + * Set PXN for user mappings
> + */
> + user_pgprot |= PTE_EXT_PXN;
> #endif
>
> for (i = 0; i < 16; i++) {
>
> --
> Catalin
thanks for the review
More information about the linux-arm-kernel
mailing list