Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2499539pxb; Tue, 9 Mar 2021 04:14:58 -0800 (PST) X-Google-Smtp-Source: ABdhPJxnA/r//ykV382atHBO4SpIzCje/uSwix4naA+/KIdBoyHGIUkDHLy/Lp7YGzMFKs7CnJZI X-Received: by 2002:aa7:dd99:: with SMTP id g25mr3672715edv.230.1615292098801; Tue, 09 Mar 2021 04:14:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615292098; cv=none; d=google.com; s=arc-20160816; b=obNBVtDZiUZp2odhGyxkJytBbJweGWJ2qSJdJUQgtJ49POZBZ4XRHokRvMWKHBc7RN 7WHNep0X/tclbnfymIv5V2kNLQcKQMZDKjvSjbNNE0oqboHHzYAdnFXygPc/56Y/cbuC 8j7qdgnOLneNyz1cpHua92Tse6fvqNZOHwx7PtXzdx8XqIkpPY9YeWMyUv6/BPt1VlYd Rt/v5BInSkS7yJnJQnFL/51iG3IUwuDfhhNaGSVNdJ5w+Et9dcdx3FgCHZEXRJsUFueT YoqX47VEN5C44tHpaj7HoOYHVgJeqgPNk1R9Ajj+4nzX2NDQXS4k6eoxfP/YtCR/O/O7 77Ig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:date:cc:to:subject:from:references:in-reply-to :message-id; bh=vw9zbY19i9M+8WLvtYMuCQGybmTGXt+tt9ymJmXZ4Fc=; b=WOMjWMKa0rt5g3wWhKCs0/SoHNVcQvhPngqSgqhGAapdA1/rFn/b7bOYxdtxUz+xln 8lg+k7UJPA36QGbmNv2qr3TrIPZ+E86eW9fHWTWx7hwUmdIt9gpE+3dIM1rH6Vco4/um cazV2afP7lPQ8Grqs7iB+pTHOSOI82/9UyNxoSpZfjoPN4AkLcNGT6JfTaZ6UFt2LVRv Xaueg1QqKReuAJG6BpX0VPbYig9mvXOxMud/g07mfpelAklnjMtvXEXvkX/teRJNpzVu 4kM3JAYzOwqkotYihDKWfJI52Kaw+4gM4z991ZLEwCwGfCL8R7Bi/rGRbvy8jDeQltWs Ic3g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j4si8860007ejm.600.2021.03.09.04.14.36; Tue, 09 Mar 2021 04:14:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231617AbhCIMLB (ORCPT + 99 others); Tue, 9 Mar 2021 07:11:01 -0500 Received: from pegase1.c-s.fr ([93.17.236.30]:31752 "EHLO pegase1.c-s.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230421AbhCIMKI (ORCPT ); Tue, 9 Mar 2021 07:10:08 -0500 Received: from localhost (mailhub1-int [192.168.12.234]) by localhost (Postfix) with ESMTP id 4DvvCx4fc5z9tyjH; Tue, 9 Mar 2021 13:10:05 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [192.168.12.234]) (amavisd-new, port 10024) with ESMTP id GqQNiQqmtXlF; Tue, 9 Mar 2021 13:10:05 +0100 (CET) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 4DvvCx3nXJz9tyjM; Tue, 9 Mar 2021 13:10:05 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id BC8618B7FC; Tue, 9 Mar 2021 13:10:06 +0100 (CET) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id 6s6vD5YAT3Fm; Tue, 9 Mar 2021 13:10:06 +0100 (CET) Received: from po16121vm.idsi0.si.c-s.fr (unknown [192.168.4.90]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 20D878B807; Tue, 9 Mar 2021 13:10:06 +0100 (CET) Received: by po16121vm.idsi0.si.c-s.fr (Postfix, from userid 0) id F27F567555; Tue, 9 Mar 2021 12:10:05 +0000 (UTC) Message-Id: In-Reply-To: References: From: Christophe Leroy Subject: [PATCH v2 39/43] powerpc/32s: Move KUEP locking/unlocking in C To: Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , npiggin@gmail.com Cc: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Date: Tue, 9 Mar 2021 12:10:05 +0000 (UTC) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This can be done in C, do it. Unrolling the loop gains approx. 15% performance. From now on, prepare_transfer_to_handler() is only for interrupts from kernel. Signed-off-by: Christophe Leroy --- arch/powerpc/include/asm/book3s/32/kup.h | 31 ------------------- arch/powerpc/include/asm/interrupt.h | 3 ++ arch/powerpc/include/asm/kup.h | 8 +++++ arch/powerpc/kernel/entry_32.S | 16 +--------- arch/powerpc/kernel/interrupt.c | 4 +++ arch/powerpc/mm/book3s32/Makefile | 1 + arch/powerpc/mm/book3s32/kuep.c | 38 ++++++++++++++++++++++++ 7 files changed, 55 insertions(+), 46 deletions(-) create mode 100644 arch/powerpc/mm/book3s32/kuep.c diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h index 73bc5d2c431d..b97ea60f6fa3 100644 --- a/arch/powerpc/include/asm/book3s/32/kup.h +++ b/arch/powerpc/include/asm/book3s/32/kup.h @@ -7,37 +7,6 @@ #ifdef __ASSEMBLY__ -.macro kuep_update_sr gpr1, gpr2 /* NEVER use r0 as gpr2 due to addis */ -101: mtsrin \gpr1, \gpr2 - addi \gpr1, \gpr1, 0x111 /* next VSID */ - rlwinm \gpr1, \gpr1, 0, 0xf0ffffff /* clear VSID overflow */ - addis \gpr2, \gpr2, 0x1000 /* address of next segment */ - bdnz 101b - isync -.endm - -.macro kuep_lock gpr1, gpr2 -#ifdef CONFIG_PPC_KUEP - li \gpr1, NUM_USER_SEGMENTS - li \gpr2, 0 - mtctr \gpr1 - mfsrin \gpr1, \gpr2 - oris \gpr1, \gpr1, SR_NX@h /* set Nx */ - kuep_update_sr \gpr1, \gpr2 -#endif -.endm - -.macro kuep_unlock gpr1, gpr2 -#ifdef CONFIG_PPC_KUEP - li \gpr1, NUM_USER_SEGMENTS - li \gpr2, 0 - mtctr \gpr1 - mfsrin \gpr1, \gpr2 - rlwinm \gpr1, \gpr1, 0, ~SR_NX /* Clear Nx */ - kuep_update_sr \gpr1, \gpr2 -#endif -.endm - #ifdef CONFIG_PPC_KUAP .macro kuap_update_sr gpr1, gpr2, gpr3 /* NEVER use r0 as gpr2 due to addis */ diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h index e6d71c2e3aa2..d4bfe94b4a68 100644 --- a/arch/powerpc/include/asm/interrupt.h +++ b/arch/powerpc/include/asm/interrupt.h @@ -34,6 +34,7 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup trace_hardirqs_off(); if (user_mode(regs)) { + kuep_lock(); current->thread.regs = regs; account_cpu_user_entry(); } @@ -91,6 +92,8 @@ static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt exception_exit(state->ctx_state); #endif + if (user_mode(regs)) + kuep_unlock(); /* * Book3S exits to user via interrupt_exit_user_prepare(), which does * context tracking, which is a cleaner way to handle PREEMPT=y diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index 7ec21af49a45..25671f711ec2 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -55,6 +55,14 @@ void setup_kuep(bool disabled); static inline void setup_kuep(bool disabled) { } #endif /* CONFIG_PPC_KUEP */ +#if defined(CONFIG_PPC_KUEP) && defined(CONFIG_PPC_BOOK3S_32) +void kuep_lock(void); +void kuep_unlock(void); +#else +static inline void kuep_lock(void) { } +static inline void kuep_unlock(void) { } +#endif + #ifdef CONFIG_PPC_KUAP void setup_kuap(bool disabled); #else diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 9c333e6db5fa..850cb17a937f 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -53,14 +53,9 @@ prepare_transfer_to_handler: andi. r0,r9,MSR_PR addi r12, r2, THREAD - beq 2f -#ifdef CONFIG_PPC_BOOK3S_32 - kuep_lock r11, r12 -#endif - blr + bnelr /* if from kernel, check interrupted DOZE/NAP mode */ -2: kuap_save_and_lock r11, r12, r9, r5, r6 lwz r12,TI_LOCAL_FLAGS(r2) mtcrf 0x01,r12 @@ -84,9 +79,6 @@ _ASM_NOKPROBE_SYMBOL(prepare_transfer_to_handler) .globl transfer_to_syscall transfer_to_syscall: SAVE_NVGPRS(r1) -#ifdef CONFIG_PPC_BOOK3S_32 - kuep_lock r11, r12 -#endif /* Calling convention has r9 = orig r0, r10 = regs */ addi r10,r1,STACK_FRAME_OVERHEAD @@ -104,9 +96,6 @@ ret_from_syscall: cmplwi cr0,r5,0 bne- 2f #endif /* CONFIG_PPC_47x */ -#ifdef CONFIG_PPC_BOOK3S_32 - kuep_unlock r5, r7 -#endif kuap_check r2, r4 lwz r4,_LINK(r1) lwz r5,_CCR(r1) @@ -287,9 +276,6 @@ interrupt_return: bne- .Lrestore_nvgprs .Lfast_user_interrupt_return: -#ifdef CONFIG_PPC_BOOK3S_32 - kuep_unlock r10, r11 -#endif kuap_check r2, r4 lwz r11,_NIP(r1) lwz r12,_MSR(r1) diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index 7082e8ee825e..727b7848c9cc 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -33,6 +33,8 @@ notrace long system_call_exception(long r3, long r4, long r5, { syscall_fn f; + kuep_lock(); + regs->orig_gpr3 = r3; if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) @@ -354,6 +356,8 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, */ kuap_user_restore(regs); #endif + kuep_unlock(); + return ret; } diff --git a/arch/powerpc/mm/book3s32/Makefile b/arch/powerpc/mm/book3s32/Makefile index 446d9de88ce4..7f0c8a78ba0c 100644 --- a/arch/powerpc/mm/book3s32/Makefile +++ b/arch/powerpc/mm/book3s32/Makefile @@ -9,3 +9,4 @@ endif obj-y += mmu.o mmu_context.o obj-$(CONFIG_PPC_BOOK3S_603) += nohash_low.o obj-$(CONFIG_PPC_BOOK3S_604) += hash_low.o tlb.o +obj-$(CONFIG_PPC_KUEP) += kuep.o diff --git a/arch/powerpc/mm/book3s32/kuep.c b/arch/powerpc/mm/book3s32/kuep.c new file mode 100644 index 000000000000..c70532568a28 --- /dev/null +++ b/arch/powerpc/mm/book3s32/kuep.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include + +#define KUEP_UPDATE_TWO_USER_SEGMENTS(n) do { \ + if (TASK_SIZE > ((n) << 28)) \ + mtsr(val1, (n) << 28); \ + if (TASK_SIZE > (((n) + 1) << 28)) \ + mtsr(val2, ((n) + 1) << 28); \ + val1 = (val1 + 0x222) & 0xf0ffffff; \ + val2 = (val2 + 0x222) & 0xf0ffffff; \ +} while (0) + +static __always_inline void kuep_update(u32 val) +{ + int val1 = val; + int val2 = (val + 0x111) & 0xf0ffffff; + + KUEP_UPDATE_TWO_USER_SEGMENTS(0); + KUEP_UPDATE_TWO_USER_SEGMENTS(2); + KUEP_UPDATE_TWO_USER_SEGMENTS(4); + KUEP_UPDATE_TWO_USER_SEGMENTS(6); + KUEP_UPDATE_TWO_USER_SEGMENTS(8); + KUEP_UPDATE_TWO_USER_SEGMENTS(10); + KUEP_UPDATE_TWO_USER_SEGMENTS(12); + KUEP_UPDATE_TWO_USER_SEGMENTS(14); +} + +void kuep_lock(void) +{ + kuep_update(mfsr(0) | SR_NX); +} + +void kuep_unlock(void) +{ + kuep_update(mfsr(0) & ~SR_NX); +} -- 2.25.0