[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAAhV-H4a+rmcTzmEfbrS3q8cS++80r6e=vZh4qp0jbaW7-YwPg@mail.gmail.com>
Date: Mon, 2 Dec 2024 11:12:00 +0800
From: Huacai Chen <chenhuacai@...nel.org>
To: Bibo Mao <maobibo@...ngson.cn>
Cc: WANG Xuerui <kernel@...0n.name>, Andrew Morton <akpm@...ux-foundation.org>,
Jiaxun Yang <jiaxun.yang@...goat.com>, loongarch@...ts.linux.dev,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] LoongArch: Add architecture specific huge_pte_clear
Applied, thanks.
Huacai
On Thu, Nov 28, 2024 at 4:30 PM Bibo Mao <maobibo@...ngson.cn> wrote:
>
> When executing mm selftests run_vmtests.sh, there is such error:
>
> BUG: Bad page state in process uffd-unit-tests pfn:00000
> page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x0
> flags: 0xffff0000002000(reserved|node=0|zone=0|lastcpupid=0xffff)
> raw: 00ffff0000002000 ffffbf0000000008 ffffbf0000000008 0000000000000000
> raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
> page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
> Modules linked in: snd_seq_dummy snd_seq snd_seq_device rfkill vfat fat
> virtio_balloon efi_pstore virtio_net pstore net_failover failover fuse
> nfnetlink virtio_scsi virtio_gpu virtio_dma_buf dm_multipath efivarfs
> CPU: 2 UID: 0 PID: 1913 Comm: uffd-unit-tests Not tainted 6.12.0 #184
> Hardware name: QEMU QEMU Virtual Machine, BIOS unknown 2/2/2022
> Stack : 900000047c8ac000 0000000000000000 9000000000223a7c 900000047c8ac000
> 900000047c8af690 900000047c8af698 0000000000000000 900000047c8af7d8
> 900000047c8af7d0 900000047c8af7d0 900000047c8af5b0 0000000000000001
> 0000000000000001 900000047c8af698 10b3c7d53da40d26 0000010000000000
> 0000000000000022 0000000fffffffff fffffffffe000000 ffff800000000000
> 000000000000002f 0000800000000000 000000017a6d4000 90000000028f8940
> 0000000000000000 0000000000000000 90000000025aa5e0 9000000002905000
> 0000000000000000 90000000028f8940 ffff800000000000 0000000000000000
> 0000000000000000 0000000000000000 9000000000223a94 000000012001839c
> 00000000000000b0 0000000000000004 0000000000000000 0000000000071c1d
> ...
> Call Trace:
> [<9000000000223a94>] show_stack+0x5c/0x180
> [<9000000001c3fd64>] dump_stack_lvl+0x6c/0xa0
> [<900000000056aa08>] bad_page+0x1a0/0x1f0
> [<9000000000574978>] free_unref_folios+0xbf0/0xd20
> [<90000000004e65cc>] folios_put_refs+0x1a4/0x2b8
> [<9000000000599a0c>] free_pages_and_swap_cache+0x164/0x260
> [<9000000000547698>] tlb_batch_pages_flush+0xa8/0x1c0
> [<9000000000547f30>] tlb_finish_mmu+0xa8/0x218
> [<9000000000543cb8>] exit_mmap+0x1a0/0x360
> [<9000000000247658>] __mmput+0x78/0x200
> [<900000000025583c>] do_exit+0x43c/0xde8
> [<9000000000256490>] do_group_exit+0x68/0x110
> [<9000000000256554>] sys_exit_group+0x1c/0x20
> [<9000000001c413b4>] do_syscall+0x94/0x130
> [<90000000002216d8>] handle_syscall+0xb8/0x158
> Disabling lock debugging due to kernel taint
> BUG: non-zero pgtables_bytes on freeing mm: -16384
>
> On LoongArch system, invalid huge pte entry should be invalid_pte_table
> or _PAGE_HUGE. And it need be the same with invalid pmd entry, since
> pmd_none() is called by function free_pgd_range(), pmd_none() return 0
> by huge_pte_clear(). So _PAGE_HUGE is treated as valid pte table and
> free_pte_range() will be called in free_pmd_range().
>
> free_pmd_range()
> pmd = pmd_offset(pud, addr);
> do {
> next = pmd_addr_end(addr, end);
> if (pmd_none_or_clear_bad(pmd))
> continue;
> free_pte_range(tlb, pmd, addr);
> } while (pmd++, addr = next, addr != end);
>
> Here invalid_pte_table is used for both invalid huge pte entry and
> pmd entry.
>
> Fixes: 09cfefb7fa70 ("LoongArch: Add memory management")
> Signed-off-by: Bibo Mao <maobibo@...ngson.cn>
> ---
> arch/loongarch/include/asm/hugetlb.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/arch/loongarch/include/asm/hugetlb.h b/arch/loongarch/include/asm/hugetlb.h
> index b837c65a4894..c8e4057734d0 100644
> --- a/arch/loongarch/include/asm/hugetlb.h
> +++ b/arch/loongarch/include/asm/hugetlb.h
> @@ -24,6 +24,16 @@ static inline int prepare_hugepage_range(struct file *file,
> return 0;
> }
>
> +#define __HAVE_ARCH_HUGE_PTE_CLEAR
> +static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
> + pte_t *ptep, unsigned long sz)
> +{
> + pte_t clear;
> +
> + pte_val(clear) = (unsigned long)invalid_pte_table;
> + set_pte_at(mm, addr, ptep, clear);
> +}
> +
> #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
> static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
> unsigned long addr, pte_t *ptep)
>
> base-commit: b86545e02e8c22fb89218f29d381fa8e8b91d815
> --
> 2.39.3
>
Powered by blists - more mailing lists