arm64: fix for -rc3
Subsystems (5)
Hi Linus,
Just one small fix here, preventing a VM_WARN_ON when a !present PMD/PUD is "freed" as part of a huge ioremap() operation. The correct behaviour is to skip the free silently in this case, which is a little weird (the function is a bit of a misnomer), but it follows the x86 implementation.
I also renewed the expiry dates on my gpg subkeys this week, so you might need to re-fetch them if you can find a working keyserver.
Cheers,
Will
--->8
The following changes since commit 57361846b52bc686112da6ca5368d11210796804:
Linux 4.19-rc2 (2018-09-02 14:37:30 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes
for you to fetch changes up to fac880c7d074fdfca874114b5c47b36aa034e4ee:
arm64: fix erroneous warnings in page freeing functions (2018-09-06 18:01:13 +0100)
----------------------------------------------------------------
arm64 fix
- Remove accidental VM_WARN_ON
----------------------------------------------------------------
Mark Rutland (1):
arm64: fix erroneous warnings in page freeing functions
arch/arm64/mm/mmu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
Quoted 5 lines · Will Deacon
Just one small fix here, preventing a
VM_WARN_ONwhen a !present PMD/PUD is "freed" as part of a hugeioremap()operation. The correct behaviour is to skip the free silently in this case, which is a little weird (the function is a bit of a misnomer), but it follows the x86 implementation.
Hmm. I've obviously pulled it, but it does strike me that maybe the confusing semantics could be fixed?
There's only one call site, and only two implementations (x86 and arm64).
Maybe the whole "read pmd, check for present" could just be in the caller, avoiding that oddity wrt name-vs-behavior.
I'm not entirely sure why that code has that special case to begin with. I guess this is the only case of a kernel mapping of a hugepage, and people wanted to avoid polluting the generic code with stuff that was only relevant for architectures that implemented it? But we already have that ioremap_pmd_enabled() guard, so architectures that don't do this wouldn't actually have any extra code.
Anyway, I'll let it be, but I think it could be a good idea to simply change the semantics, and in the process also make it a lot clearer what that thing actually is expected to do.
Linus
Hi Linus,
Quoted 22 lines · Linus Torvalds
Quoted 5 lines · Will Deacon
Just one small fix here, preventing a
VM_WARN_ONwhen a !present PMD/PUD is "freed" as part of a hugeioremap()operation. The correct behaviour is to skip the free silently in this case, which is a little weird (the function is a bit of a misnomer), but it follows the x86 implementation.Hmm. I've obviously pulled it, but it does strike me that maybe the confusing semantics could be fixed?
There's only one call site, and only two implementations (x86 and arm64).
Maybe the whole "read pmd, check for present" could just be in the caller, avoiding that oddity wrt name-vs-behavior.
I'm not entirely sure why that code has that special case to begin with. I guess this is the only case of a kernel mapping of a hugepage, and people wanted to avoid polluting the generic code with stuff that was only relevant for architectures that implemented it? But we already have that
ioremap_pmd_enabled()guard, so architectures that don't do this wouldn't actually have any extra code.
Quoted 3 lines
Anyway, I'll let it be, but I think it could be a good idea to simply change the semantics, and in the process also make it a lot clearer what that thing actually is expected to do.
Yeah, I agree, and it's better to fix it before it grows lots of other users. I had a hack at it (see below), but note:
* I ended up reworking the phys_addr calculations to avoid the misnomer there as well (namely that phys_addr isn't a physical address!).
* The huge p4d code is only half implemented in mainline and unused by any architecture. I've added some of the missing bits, or we could just rip it out.
* The shape of the code is duplicated, but I couldn't figure out a cleaner way to do it and maintain the type-checking for the different levels.
Happy to send as a proper patch if you think this is the right sort of idea.
Will
--->8
arch/arm64/mm/mmu.c +7 -6
@@ -985,10 +985,8 @@ int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr) pmd =READ_ONCE (*pmdp); -if (!pmd_present (pmd)) -return 1 ;if (!pmd_table (pmd)) { -VM_WARN_ON (!pmd_table (pmd)); +VM_WARN_ON (1 );return 1 ; }
@@ -1008,10 +1006,8 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr) pud =READ_ONCE (*pudp); -if (!pud_present (pud)) -return 1 ;if (!pud_table (pud)) { -VM_WARN_ON (!pud_table (pud)); +VM_WARN_ON (1 );return 1 ; }
@@ -1028,3 +1024,8 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)pmd_free (NULL , table);return 1 ; } + +int p4d_free_pud_page (p4d_t *p4d,unsigned long addr) +{ +return 0 ;/* Don't attempt a block mapping */ +}
arch/x86/mm/pgtable.c +8 -6
@@ -779,6 +779,14 @@ int pmd_clear_huge(pmd_t *pmd)return 0 ; } +/* +* Until we support 512GB pages, skip them in the vmap area. +*/ +int p4d_free_pud_page (p4d_t *p4d,unsigned long addr) +{ +return 0 ; +} +#ifdef CONFIG_X86_64 /** * pud_free_pmd_page - Clear pud entry and free pmd page.
@@ -796,9 +804,6 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)pte_t *pte;int i; -if (pud_none (*pud)) -return 1 ; - pmd = (pmd_t *)pud_page_vaddr (*pud); pmd_sv = (pmd_t *)__get_free_page (GFP_KERNEL );if (!pmd_sv)
@@ -840,9 +845,6 @@ int pmd_free_pte_page(pmd_t *pmd, unsigned long addr) {pte_t *pte; -if (pmd_none (*pmd)) -return 1 ; - pte = (pte_t *)pmd_page_vaddr (*pmd);pmd_clear (pmd);
include/asm-generic/pgtable.h +5 -0
@@ -1019,6 +1019,7 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);int pmd_set_huge (pmd_t *pmd,phys_addr_t addr,pgprot_t prot);int pud_clear_huge (pud_t *pud);int pmd_clear_huge (pmd_t *pmd); +int p4d_free_pud_page (p4d_t *pmd,unsigned long addr);int pud_free_pmd_page (pud_t *pud,unsigned long addr);int pmd_free_pte_page (pmd_t *pmd,unsigned long addr);#else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
@@ -1046,6 +1047,10 @@ static inline int pmd_clear_huge(pmd_t *pmd) {return 0 ; } +static inline int p4d_free_pud_page (p4d_t *pmd,unsigned long addr) +{ +return 0 ; +}static inline int pud_free_pmd_page (pud_t *pud,unsigned long addr) {return 0 ;
lib/ioremap.c +71 -32
168 lines not on this page · raw message
Quoted 3 lines · Will Deacon
Happy to send as a proper patch if you think this is the right sort of idea.
Looks sane to me,
Linus