Loading arch/arm64/include/asm/pgtable.h +1 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,7 @@ static inline int pmd_protnone(pmd_t pmd) #define pud_write(pud) pte_write(pud_pte(pud)) #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) #define pfn_pud(pfn,prot) (__pud(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) #define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) Loading arch/arm64/mm/mmu.c +27 −6 Original line number Diff line number Diff line Loading @@ -135,6 +135,17 @@ static phys_addr_t __init early_pgtable_alloc(void) return phys; } static bool pgattr_change_is_safe(u64 old, u64 new) { /* * The following mapping attributes may be updated in live * kernel mappings without the need for break-before-make. */ static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE; return old == 0 || new == 0 || ((old ^ new) & ~mask) == 0; } static void alloc_init_pte(pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, pgprot_t prot, Loading Loading @@ -826,23 +837,33 @@ int __init arch_ioremap_pmd_supported(void) int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) { /* ioremap_page_range doesn't honour BBM */ if (pud_present(READ_ONCE(*pud))) pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pud)), pud_val(new_pud))) return 0; BUG_ON(phys & ~PUD_MASK); set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); set_pud(pud, new_pud); return 1; } int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) { /* ioremap_page_range doesn't honour BBM */ if (pmd_present(READ_ONCE(*pmd))) pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmd)), pmd_val(new_pmd))) return 0; BUG_ON(phys & ~PMD_MASK); set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); set_pmd(pmd, new_pmd); return 1; } Loading Loading
arch/arm64/include/asm/pgtable.h +1 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,7 @@ static inline int pmd_protnone(pmd_t pmd) #define pud_write(pud) pte_write(pud_pte(pud)) #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) #define pfn_pud(pfn,prot) (__pud(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) #define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) Loading
arch/arm64/mm/mmu.c +27 −6 Original line number Diff line number Diff line Loading @@ -135,6 +135,17 @@ static phys_addr_t __init early_pgtable_alloc(void) return phys; } static bool pgattr_change_is_safe(u64 old, u64 new) { /* * The following mapping attributes may be updated in live * kernel mappings without the need for break-before-make. */ static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE; return old == 0 || new == 0 || ((old ^ new) & ~mask) == 0; } static void alloc_init_pte(pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, pgprot_t prot, Loading Loading @@ -826,23 +837,33 @@ int __init arch_ioremap_pmd_supported(void) int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) { /* ioremap_page_range doesn't honour BBM */ if (pud_present(READ_ONCE(*pud))) pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pud)), pud_val(new_pud))) return 0; BUG_ON(phys & ~PUD_MASK); set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); set_pud(pud, new_pud); return 1; } int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) { /* ioremap_page_range doesn't honour BBM */ if (pmd_present(READ_ONCE(*pmd))) pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))); pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmd)), pmd_val(new_pmd))) return 0; BUG_ON(phys & ~PMD_MASK); set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); set_pmd(pmd, new_pmd); return 1; } Loading