From patchwork Tue Jul 25 06:14:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enze Li X-Patchwork-Id: 13325910 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D814C00528 for ; Tue, 25 Jul 2023 06:15:29 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 25795900002; Tue, 25 Jul 2023 02:15:29 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 16BD08E0003; Tue, 25 Jul 2023 02:15:29 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EFF80900002; Tue, 25 Jul 2023 02:15:28 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id DF6EA8E0003 for ; Tue, 25 Jul 2023 02:15:28 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id B0E2280C5A for ; Tue, 25 Jul 2023 06:15:28 +0000 (UTC) X-FDA: 81049122336.04.4B4DEF9 Received: from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232]) by imf17.hostedemail.com (Postfix) with ESMTP id D7D244000C for ; Tue, 25 Jul 2023 06:15:25 +0000 (UTC) Authentication-Results: imf17.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf17.hostedemail.com: domain of lienze@kylinos.cn designates 124.126.103.232 as permitted sender) smtp.mailfrom=lienze@kylinos.cn ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1690265726; a=rsa-sha256; cv=none; b=cTcMdmO8EBvCYS8+7bLMy3/NWidKzMlJuH/gqB7+y1p6oBg9y9eG1A9w+EBjbkoJxa7pn8 xvlJFGPIbNtpuAw32c7FCNiMYoAuo3/SkXRoQXd05rn/IcOjpR0XZebMZiPKfZEvxuSC/K 4jXccBjl15Lmj39kn/TXdEi/olAXgTU= ARC-Authentication-Results: i=1; imf17.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf17.hostedemail.com: domain of lienze@kylinos.cn designates 124.126.103.232 as permitted sender) smtp.mailfrom=lienze@kylinos.cn ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1690265726; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EqW6kJ87jfc/UoorJHCNkGGBtCR16wyXTZDbfFoAbyY=; b=ZPNfL3Nfhf0r2XvfJsGgNLXKvyWuv2N2k5Gg57stmr5QwVyCCnj0Ec+OUB9C1x2foM9s6s BTm4Rn3fS/EUdYGSadvUXT6MEM14S5G0O/QaYwcP4ajs30ADt8wHpPE6C/Oe2WQLexHihH ZupZ23Qqsmls/QmtdHiKemdsk6KFtC0= X-UUID: 3f0d37b293b84437aff8eecdace72e24-20230725 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.28,REQID:d8a88afa-7b8d-4f33-a7ea-af79e1cee8d2,IP:15, URL:0,TC:0,Content:0,EDM:0,RT:0,SF:-15,FILE:0,BULK:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-INFO: VERSION:1.1.28,REQID:d8a88afa-7b8d-4f33-a7ea-af79e1cee8d2,IP:15,UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:-15,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:0 X-CID-META: VersionHash:176cd25,CLOUDID:1d6ec1b3-a467-4aa9-9e04-f584452e3794,B ulkID:230725141514S69XBC26,BulkQuantity:0,Recheck:0,SF:38|24|17|19|44|102, TC:nil,Content:0,EDM:-3,IP:-2,URL:1,File:nil,Bulk:nil,QS:nil,BEC:nil,COL:0 ,OSI:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_ULS,TF_CID_SPAM_SNR,TF_CID_SPAM_FAS,TF_CID_SPAM_FSD, TF_CID_SPAM_FSI X-UUID: 3f0d37b293b84437aff8eecdace72e24-20230725 X-User: lienze@kylinos.cn Received: from ubuntu.. [(39.156.73.12)] by mailgw (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 755063753; Tue, 25 Jul 2023 14:15:12 +0800 From: Enze Li To: chenhuacai@kernel.org, kernel@xen0n.name, loongarch@lists.linux.dev, glider@google.com, elver@google.com, akpm@linux-foundation.org, kasan-dev@googlegroups.com, linux-mm@kvack.org Cc: zhangqing@loongson.cn, yangtiezhu@loongson.cn, dvyukov@google.com, Enze Li Subject: [PATCH 4/4 v2] LoongArch: Add KFENCE support Date: Tue, 25 Jul 2023 14:14:51 +0800 Message-Id: <20230725061451.1231480-5-lienze@kylinos.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230725061451.1231480-1-lienze@kylinos.cn> References: <20230725061451.1231480-1-lienze@kylinos.cn> MIME-Version: 1.0 X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: D7D244000C X-Stat-Signature: 8nihupp913w19ukm5oi1npifaimcyndm X-Rspam-User: X-HE-Tag: 1690265725-949355 X-HE-Meta: U2FsdGVkX1/c6LH569kkpDNBLgQz2W5g/gkP/v4THOKjRqzeWI6QuRvgOmHDD1t5HIRrWzfDSLxNNbi5upeuaZYPsRc1x/vhIN14YequabO61f+Uj+s8H3QoT5YTBfCPClYhwyx1EQOgb5O24ajwV7eEkIl6vPRUYRTtAZsWZirYp/ka921J/pva5VL1rXkOeObof8YXgapN8f7+PX6HcBYKN6Wj45kGOVAweceGsPZAOc9RyxqNxMVYrw8+FNl/3z2dFW7LoMsBFWjb7P8nyUJyZKqm8+J+DbTHffyFsfMz6OhSqVuS2ntukNvcL14tQ4doY3xQJ3oM6bADy+M4tOfrQtHpZN4cx4GxVpn775WkJ0vFt9InhtbG9wG7tYkE9fzhmwcYTvTXwffw88u9nOYJR4V1q1vaZU2b5po2GGya6tr/tMZBjhwvjNRDpHhk+nFSuSjTs/TxkzxNq8ddD5fLKAttXWtORW7TMXEV36lGLnS+r8c1gwzshMFnEkCQmJlgQk6GZP2J4cCf78mmcd2ZnX8S29vFE5xHxsBh1il/2u27seBO99+FwKqQtXeGM0Q/GUel/J8c8/Bmz6+nW6epbIpxydaYiUV0BbfYK+nQn72J+ufl0+PbOQxafJ5DUeCN5Vmo0aWwS9aPfP+J43h+xjfDJv93/rqsrYcL2XrvG0+6ehr4sO+0A9PDcIHSmaMSng2toIDCLE2euYZgii65SAKGS0BgZL9lB1z2bB65JGcFTlknLAUc865uW6C5KP0iqLxFXTVl2ZNdDdoYFCw1cn6i1E4c3Vth6Vvrp2qkX/oxAISBHp8SB4+7kDGMTNUUFVWKESQFdZa9GFZ5ZhhK8G9GpK9osoreW5s3GRmYD8VTueW/GNDx/PDOSu6rF6mbhQWaR/QqPVVP9giURXrM34JSgfzozNkVnACli0p+GYS5xlT5DVHlg0fcJrfC/W4i6ztdFRP3JMMsjsA YJ3kYzpe r4j3eKFNXEJTVVCq3HYRnAuL9/c+l24OjMvfHKppwRr66nCHNVjNBvCzdG60+VUxqRDp323ALWMecn5GChiSSaPtJbmLpwdRHc4TMVBtM0e317Z2B9opFsHi0cw== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The LoongArch architecture is quite different from other architectures. When the allocating of KFENCE itself is done, it is mapped to the direct mapping configuration window [1] by default on LoongArch. It means that it is not possible to use the page table mapped mode which required by the KFENCE system and therefore it should be remapped to the appropriate region. This patch adds architecture specific implementation details for KFENCE. In particular, this implements the required interface in . Tested this patch by running the testcases and all passed. [1] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#virtual-address-space-and-address-translation-mode Signed-off-by: Enze Li --- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/kfence.h | 62 ++++++++++++++++++++++++++++ arch/loongarch/include/asm/pgtable.h | 14 ++++++- arch/loongarch/mm/fault.c | 22 ++++++---- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 arch/loongarch/include/asm/kfence.h diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 70635ea3d1e4..5b63b16be49e 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -91,6 +91,7 @@ config LOONGARCH select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL_RELATIVE + select HAVE_ARCH_KFENCE select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK diff --git a/arch/loongarch/include/asm/kfence.h b/arch/loongarch/include/asm/kfence.h new file mode 100644 index 000000000000..fb39076fe4d7 --- /dev/null +++ b/arch/loongarch/include/asm/kfence.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * KFENCE support for LoongArch. + * + * Author: Enze Li + * Copyright (C) 2022-2023 KylinSoft Corporation. + */ + +#ifndef _ASM_LOONGARCH_KFENCE_H +#define _ASM_LOONGARCH_KFENCE_H + +#include +#include +#include + +static inline bool arch_kfence_init_pool(void) +{ + char *kfence_pool = __kfence_pool; + struct vm_struct *area; + int err; + + area = __get_vm_area_caller(KFENCE_POOL_SIZE, VM_IOREMAP, + KFENCE_AREA_START, KFENCE_AREA_END, + __builtin_return_address(0)); + if (!area) + return false; + + __kfence_pool = (char *)area->addr; + err = ioremap_page_range((unsigned long)__kfence_pool, + (unsigned long)__kfence_pool + KFENCE_POOL_SIZE, + virt_to_phys((void *)kfence_pool), + PAGE_KERNEL); + if (err) { + free_vm_area(area); + return false; + } + + return true; +} + +/* Protect the given page and flush TLB. */ +static inline bool kfence_protect_page(unsigned long addr, bool protect) +{ + pte_t *pte = virt_to_kpte(addr); + + if (WARN_ON(!pte) || pte_none(*pte)) + return false; + + if (protect) + set_pte(pte, __pte(pte_val(*pte) & ~(_PAGE_VALID | _PAGE_PRESENT))); + else + set_pte(pte, __pte(pte_val(*pte) | (_PAGE_VALID | _PAGE_PRESENT))); + + /* Flush this CPU's TLB. */ + preempt_disable(); + local_flush_tlb_one(addr); + preempt_enable(); + + return true; +} + +#endif /* _ASM_LOONGARCH_KFENCE_H */ diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index 98a0c98de9d1..2702a6ba7122 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -77,6 +77,13 @@ extern unsigned long zero_page_mask; (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))) #define __HAVE_COLOR_ZERO_PAGE +#ifdef CONFIG_KFENCE +#define KFENCE_AREA_SIZE \ + (((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 + 2) * PAGE_SIZE) +#else +#define KFENCE_AREA_SIZE 0 +#endif + /* * TLB refill handlers may also map the vmalloc area into xkvrange. * Avoid the first couple of pages so NULL pointer dereferences will @@ -88,11 +95,16 @@ extern unsigned long zero_page_mask; #define VMALLOC_START MODULES_END #define VMALLOC_END \ (vm_map_base + \ - min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, (1UL << cpu_vabits)) - PMD_SIZE - VMEMMAP_SIZE) + min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, (1UL << cpu_vabits)) - PMD_SIZE - VMEMMAP_SIZE - KFENCE_AREA_SIZE) #define vmemmap ((struct page *)((VMALLOC_END + PMD_SIZE) & PMD_MASK)) #define VMEMMAP_END ((unsigned long)vmemmap + VMEMMAP_SIZE - 1) +#ifdef CONFIG_KFENCE +#define KFENCE_AREA_START VMEMMAP_END +#define KFENCE_AREA_END (KFENCE_AREA_START + KFENCE_AREA_SIZE) +#endif + #define pte_ERROR(e) \ pr_err("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) #ifndef __PAGETABLE_PMD_FOLDED diff --git a/arch/loongarch/mm/fault.c b/arch/loongarch/mm/fault.c index da5b6d518cdb..c0319128b221 100644 --- a/arch/loongarch/mm/fault.c +++ b/arch/loongarch/mm/fault.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,8 @@ int show_unhandled_signals = 1; -static void __kprobes no_context(struct pt_regs *regs, unsigned long address) +static void __kprobes no_context(struct pt_regs *regs, unsigned long address, + unsigned long write) { const int field = sizeof(unsigned long) * 2; @@ -38,6 +40,9 @@ static void __kprobes no_context(struct pt_regs *regs, unsigned long address) if (fixup_exception(regs)) return; + if (kfence_handle_page_fault(address, write, regs)) + return; + /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. @@ -51,14 +56,15 @@ static void __kprobes no_context(struct pt_regs *regs, unsigned long address) die("Oops", regs); } -static void __kprobes do_out_of_memory(struct pt_regs *regs, unsigned long address) +static void __kprobes do_out_of_memory(struct pt_regs *regs, unsigned long address, + unsigned long write) { /* * We ran out of memory, call the OOM killer, and return the userspace * (which will retry the fault, or kill us if we got oom-killed). */ if (!user_mode(regs)) { - no_context(regs, address); + no_context(regs, address, write); return; } pagefault_out_of_memory(); @@ -69,7 +75,7 @@ static void __kprobes do_sigbus(struct pt_regs *regs, { /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) { - no_context(regs, address); + no_context(regs, address, write); return; } @@ -90,7 +96,7 @@ static void __kprobes do_sigsegv(struct pt_regs *regs, /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) { - no_context(regs, address); + no_context(regs, address, write); return; } @@ -149,7 +155,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, */ if (address & __UA_LIMIT) { if (!user_mode(regs)) - no_context(regs, address); + no_context(regs, address, write); else do_sigsegv(regs, write, address, si_code); return; @@ -211,7 +217,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, if (fault_signal_pending(fault, regs)) { if (!user_mode(regs)) - no_context(regs, address); + no_context(regs, address, write); return; } @@ -232,7 +238,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, if (unlikely(fault & VM_FAULT_ERROR)) { mmap_read_unlock(mm); if (fault & VM_FAULT_OOM) { - do_out_of_memory(regs, address); + do_out_of_memory(regs, address, write); return; } else if (fault & VM_FAULT_SIGSEGV) { do_sigsegv(regs, write, address, si_code);