diff options
author | David S. Miller <davem@davemloft.net> | 2020-06-03 03:45:51 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-06-03 03:45:51 +0200 |
commit | 7104e162b772c777d84298f25c8431da4cf5206d (patch) | |
tree | 3b849e4c43873e8fc1fead51e5531bcb2d0d2b19 | |
parent | sparc32: register memory occupied by kernel as memblock.memory (diff) | |
parent | sparc32: mm: Only call ctor()/dtor() functions for first and last user (diff) | |
download | linux-7104e162b772c777d84298f25c8431da4cf5206d.tar.xz linux-7104e162b772c777d84298f25c8431da4cf5206d.zip |
Merge branch 'sparc32-SRMMU-fixes-for-SMP'
Will Deacon says:
====================
sparc32 SRMMU fixes for SMP
Enabling SMP for sparc32 uncovered some issues in the SRMMU page-table
allocation code. One of these was introduced by me, but the other two
seem to have been there a while and are probably just exposed more
easily by my recent changes.
Tested on QEMU. I'm assuming these will go via David's tree.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/mm/srmmu.c | 15 | ||||
-rw-r--r-- | mm/Kconfig | 4 |
2 files changed, 15 insertions, 4 deletions
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c861c0f0df73..116d19a390f2 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -364,10 +364,13 @@ pgtable_t pte_alloc_one(struct mm_struct *mm) if ((ptep = pte_alloc_one_kernel(mm)) == 0) return NULL; page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT); - if (!pgtable_pte_page_ctor(page)) { - __free_page(page); - return NULL; + spin_lock(&mm->page_table_lock); + if (page_ref_inc_return(page) == 2 && !pgtable_pte_page_ctor(page)) { + page_ref_dec(page); + ptep = NULL; } + spin_unlock(&mm->page_table_lock); + return ptep; } @@ -376,7 +379,11 @@ void pte_free(struct mm_struct *mm, pgtable_t ptep) struct page *page; page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT); - pgtable_pte_page_dtor(page); + spin_lock(&mm->page_table_lock); + if (page_ref_dec_return(page) == 1) + pgtable_pte_page_dtor(page); + spin_unlock(&mm->page_table_lock); + srmmu_free_nocache(ptep, SRMMU_PTE_TABLE_SIZE); } diff --git a/mm/Kconfig b/mm/Kconfig index c1acc34c1c35..97458119cce8 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -192,6 +192,9 @@ config MEMORY_HOTREMOVE # Default to 4 for wider testing, though 8 might be more appropriate. # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. +# SPARC32 allocates multiple pte tables within a single page, and therefore +# a per-page lock leads to problems when multiple tables need to be locked +# at the same time (e.g. copy_page_range()). # DEBUG_SPINLOCK and DEBUG_LOCK_ALLOC spinlock_t also enlarge struct page. # config SPLIT_PTLOCK_CPUS @@ -199,6 +202,7 @@ config SPLIT_PTLOCK_CPUS default "999999" if !MMU default "999999" if ARM && !CPU_CACHE_VIPT default "999999" if PARISC && !PA20 + default "999999" if SPARC32 default "4" config ARCH_ENABLE_SPLIT_PMD_PTLOCK |