Received: by 2002:ab2:6a05:0:b0:1f8:1780:a4ed with SMTP id w5csp1907772lqo; Mon, 13 May 2024 01:55:54 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWc1XrP9t49ePb6zHxNEkNgWC2mDakeyuAf/NUgw/GYbpYF399yHpsB9sYE7WnPgYT/ji/Npdkga1tj3cem7e8mw9RKPecJhFOmwPkA0A== X-Google-Smtp-Source: AGHT+IGVPGUIaDNwospZGlHrxxYs//xFAYMK/nm6aCPfwGyHjmEeI0LpVfdMTiTZAuze9TH/hFxB X-Received: by 2002:a17:90b:3650:b0:2b1:116c:5085 with SMTP id 98e67ed59e1d1-2b6cc44fa3amr8251391a91.14.1715590554068; Mon, 13 May 2024 01:55:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715590554; cv=pass; d=google.com; s=arc-20160816; b=jLsGeqx9WItOBABJnZA7JYyB7gpV1GuFQ/sYxHcmvDI5O0y1WlQngTEkI3wZvq+4Bf i7FHYn3EEqpPeFKm2g1iCfnrgX0DMe8vyD0TMhm73UxZgUaiIdlVwVBvT3twKWjzWJoy rMO5vzyGLeOQRERkwg7ITb3pFa8TGALe/pcKkOOF9GxcPfBEN8dLdMp9Y43/20+0JKND d3V4h7JWRp86Gc6+nGzNm6S+0nXfpfl2uvyz8pXkjHQLhFUQV9bEqWAnqVn9815XClQi yL+CGKeGuBxWZhPIuEh6zZStfLwaZeXK96Nm3385JvIfOFEYZoDwxc+6s1p47ziFOwoJ FuJA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:list-unsubscribe:list-subscribe :list-id:precedence:dkim-signature; bh=HdBEm+7Bzyf8ybTn28Qe65zyFvN0QEjy08+SqQ/NGoI=; fh=omXmxLmCTjKrgzMwHZXtX7PHwuAyG7XO5rMCui9mvbk=; b=t0GgXeW06i7oRnGPdKU/hfJfeCPinsABRXoiPKg5IfPBQb1JSZcWVgFAldiU23pzww QBYM8GNQrqOoN3j53j7zeDztRzIEAS6KHwZdbaMwjX2DcK3UkltKIJjYrTfo5Mij60y3 BMil33+I9scP7sbIVI3Afw0vcGaKdrAj5ECYJuROEdgPvL0Hs2v1CML0BQOnoRSmWYFj vim2rN5YiAgSp7Vzq1cmuGPgx7SH6RiTb2xO4d0G+6wAkJf2zNTgKJ04X3NqY7NvjvQU iFoZUgLqMR9ZQihSPeEq/bfUlPmBqBdDyAgu5tR1jW8yjpjaN4ET/pquGxxn6r24r6J5 bN+Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=LdmiXlMa; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-177361-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-177361-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id 98e67ed59e1d1-2b670e350aasi9054449a91.11.2024.05.13.01.55.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 May 2024 01:55:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-177361-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=LdmiXlMa; arc=pass (i=1 spf=pass spfdomain=sifive.com dkim=pass dkdomain=sifive.com dmarc=pass fromdomain=sifive.com); spf=pass (google.com: domain of linux-kernel+bounces-177361-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-177361-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 9D5912828B7 for ; Mon, 13 May 2024 08:45:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 17C601482FC; Mon, 13 May 2024 08:45:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b="LdmiXlMa" Received: from mail-yw1-f173.google.com (mail-yw1-f173.google.com [209.85.128.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAC761474C8 for ; Mon, 13 May 2024 08:45:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.173 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715589933; cv=none; b=WHFz8KMVvH9ALeCXiy7qKif68iQVPA2NO32X4CnHN3aBaiuUGHz396EOEuUs0BazavsehOOyDuwSGw1/gy7GFh2k9RXYOHO/seFu58wM9wouL8+0zbYVqve7cWgEZB4CFveYBrXnCWexXQmOX6o5vvk8xvbHHHXRgF7uHwM/++0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715589933; c=relaxed/simple; bh=t9B6PGb5qBLbhtEQThWWPBAUkBUONTNLxQ9X0tPf2Co=; h=MIME-Version:References:In-Reply-To:From:Date:Message-ID:Subject: To:Cc:Content-Type; b=RPZZzz7qP22UZBJ2iopcVw0e8cMJdCsxFtw0NUmZ0Kq0Awcz8iw2hmP8DzhsU0tllPdi2rP4/06dXjG2gVHKlaEalfSXkHtfB4FJB1RYThgW3kkG3oUZrruxMVOADh3+rE5gP9EysnqkEtNCQNOhbBn9/ie5WNS6JWr3JNv/LRA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com; spf=pass smtp.mailfrom=sifive.com; dkim=pass (2048-bit key) header.d=sifive.com header.i=@sifive.com header.b=LdmiXlMa; arc=none smtp.client-ip=209.85.128.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-yw1-f173.google.com with SMTP id 00721157ae682-61af74a010aso37716077b3.0 for ; Mon, 13 May 2024 01:45:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1715589930; x=1716194730; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=HdBEm+7Bzyf8ybTn28Qe65zyFvN0QEjy08+SqQ/NGoI=; b=LdmiXlMaZuIGpUkElXgUgykzCX0nX8SAkiSOdxa25Tnt7HzUIf/vOGUkFIkllsZIKJ wreRO1xk5FPl6rBxMX23aj4/O7fJu9nmj4ngXAF2yrpiVJrdmSANqY0uudbYJmzDJRdf M12gWm9ImKNVAJW8EIMKf/vc9Npne38HKVU23Pd0S811Bx855RMSZGyqC+cBrEmIefVd gC/38madTYtYprZCQpdgOimRQSHavbK3Ew+ScAkJczE3aB1vrRoIUfRhCDP7m1tyALTc Tkhhx9mrbxPR3LCyTIAEt7uiqI/Ih24Fbgk+azv25l2UBAD6jyxaYcPb9aP26ZSBsfOl ylAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715589930; x=1716194730; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HdBEm+7Bzyf8ybTn28Qe65zyFvN0QEjy08+SqQ/NGoI=; b=lj24HxEwOaDQAWz2Pl0uC1YWk50PMlj5M7W6K+eUktVaFII8MFnXMdiuXu0K4UzdtP sS77DEzIB1O2b6/r5w0w3hzKfo3vb4U212L+LexpStQDw6uH/vQzXGBBr6h2L7Jq2XBe tm1J6HkD+ZfJjP4585WEJYg0XLRSaue42hYlANKphq6A0LNJmH8dzhSmNkGhMbjeknlS 5y/jm9wznReaodKH7v5MLhp+oKgMKEdUbWo8mtK5W9N/yKjOuxVDlhnS5UUbqOaBv6JT EKxI7TEr0cRyx/MUQq0AQpccjFpe/Cs5t/FZUGwDdl1uYnvO+fZNSZnR9ZIdukRPDjdC 6yeg== X-Forwarded-Encrypted: i=1; AJvYcCWtvKmq+D/KSprPF5tHMllcxR6GZL5MO/s5ONG40i280Xs3+/NlEb/GoXi0l1NWxwubD3GCpyDXk8W1bCbeQteapTSeqtjv+Gtl65Ly X-Gm-Message-State: AOJu0YxXzm/gOe0GGfOpk0eircZ/nRoY/9AhjpK+yhdp+GRavmf1uOVp t+Gou7z3iVGzNtXQ7yUI8cvi7CYYRIGBKPxsot7Ms+QlmhFDOscsvvtE6fre+1/mVKMyjfQrgYw bh6O8Zw6lMdydWtisLLqfTpW+oUhnK+n3gTQ5rQ== X-Received: by 2002:a05:690c:6209:b0:61a:e947:550d with SMTP id 00721157ae682-622b013826fmr109570167b3.44.1715589929689; Mon, 13 May 2024 01:45:29 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 References: <20240503-dev-charlie-support_thead_vector_6_9-v6-0-cb7624e65d82@rivosinc.com> <20240503-dev-charlie-support_thead_vector_6_9-v6-13-cb7624e65d82@rivosinc.com> In-Reply-To: <20240503-dev-charlie-support_thead_vector_6_9-v6-13-cb7624e65d82@rivosinc.com> From: Andy Chiu Date: Mon, 13 May 2024 16:45:18 +0800 Message-ID: Subject: Re: [PATCH v6 13/17] riscv: vector: Support xtheadvector save/restore To: Charlie Jenkins Cc: Conor Dooley , Rob Herring , Krzysztof Kozlowski , Paul Walmsley , Palmer Dabbelt , Albert Ou , Guo Ren , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Conor Dooley , Evan Green , =?UTF-8?B?Q2zDqW1lbnQgTMOpZ2Vy?= , Jonathan Corbet , Shuah Khan , linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Palmer Dabbelt , linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Charlie, Sorry, I am late on this. I haven't looked through the entire series yet, but here is something that I thought worth bringing up sooner. On Sat, May 4, 2024 at 2:22=E2=80=AFAM Charlie Jenkins wrote: > > Use alternatives to add support for xtheadvector vector save/restore > routines. > > Signed-off-by: Charlie Jenkins > --- > arch/riscv/Kconfig.vendor | 13 ++ > arch/riscv/include/asm/csr.h | 6 + > arch/riscv/include/asm/switch_to.h | 2 +- > arch/riscv/include/asm/vector.h | 247 ++++++++++++++++++++++++++-= ------ > arch/riscv/kernel/cpufeature.c | 2 +- > arch/riscv/kernel/kernel_mode_vector.c | 8 +- > arch/riscv/kernel/process.c | 4 +- > arch/riscv/kernel/signal.c | 6 +- > arch/riscv/kernel/vector.c | 13 +- > 9 files changed, 233 insertions(+), 68 deletions(-) > > diff --git a/arch/riscv/Kconfig.vendor b/arch/riscv/Kconfig.vendor > index aa5a191e659e..edf49f3065ac 100644 > --- a/arch/riscv/Kconfig.vendor > +++ b/arch/riscv/Kconfig.vendor > @@ -13,6 +13,19 @@ config RISCV_ISA_VENDOR_EXT_THEAD > extensions. Without this option enabled, T-Head vendor extensio= ns will > not be detected at boot and their presence not reported to user= space. > > + If you don't know what to do here, say Y. > + > +config RISCV_ISA_XTHEADVECTOR > + bool "xtheadvector extension support" > + depends on RISCV_ISA_VENDOR_EXT_THEAD > + depends on RISCV_ISA_V > + depends on FPU > + default y > + help > + Say N here if you want to disable all xtheadvector related proc= edure > + in the kernel. This will disable vector for any T-Head board th= at > + contains xtheadvector rather than the standard vector. > + > If you don't know what to do here, say Y. > endmenu > > diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h > index e5a35efd56e0..13657d096e7d 100644 > --- a/arch/riscv/include/asm/csr.h > +++ b/arch/riscv/include/asm/csr.h > @@ -30,6 +30,12 @@ > #define SR_VS_CLEAN _AC(0x00000400, UL) > #define SR_VS_DIRTY _AC(0x00000600, UL) > > +#define SR_VS_THEAD _AC(0x01800000, UL) /* xtheadvector Statu= s */ > +#define SR_VS_OFF_THEAD _AC(0x00000000, UL) > +#define SR_VS_INITIAL_THEAD _AC(0x00800000, UL) > +#define SR_VS_CLEAN_THEAD _AC(0x01000000, UL) > +#define SR_VS_DIRTY_THEAD _AC(0x01800000, UL) > + > #define SR_XS _AC(0x00018000, UL) /* Extension Status */ > #define SR_XS_OFF _AC(0x00000000, UL) > #define SR_XS_INITIAL _AC(0x00008000, UL) > diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/= switch_to.h > index 7efdb0584d47..ada6b5cf2d94 100644 > --- a/arch/riscv/include/asm/switch_to.h > +++ b/arch/riscv/include/asm/switch_to.h > @@ -78,7 +78,7 @@ do { \ > struct task_struct *__next =3D (next); \ > if (has_fpu()) \ > __switch_to_fpu(__prev, __next); \ > - if (has_vector()) \ > + if (has_vector() || has_xtheadvector()) \ > __switch_to_vector(__prev, __next); \ > ((last) =3D __switch_to(__prev, __next)); \ > } while (0) > diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vec= tor.h > index 731dcd0ed4de..db851dc81870 100644 > --- a/arch/riscv/include/asm/vector.h > +++ b/arch/riscv/include/asm/vector.h > @@ -18,6 +18,27 @@ > #include > #include > #include > +#include > +#include > +#include > + > +#define __riscv_v_vstate_or(_val, TYPE) ({ \ > + typeof(_val) _res =3D _val; = \ > + if (has_xtheadvector()) \ > + _res =3D (_res & ~SR_VS_THEAD) | SR_VS_##TYPE##_THEAD; = \ > + else \ > + _res =3D (_res & ~SR_VS) | SR_VS_##TYPE; = \ > + _res; \ > +}) > + > +#define __riscv_v_vstate_check(_val, TYPE) ({ \ > + bool _res; \ > + if (has_xtheadvector()) \ > + _res =3D ((_val) & SR_VS_THEAD) =3D=3D SR_VS_##TYPE##_THE= AD; \ > + else \ > + _res =3D ((_val) & SR_VS) =3D=3D SR_VS_##TYPE; = \ > + _res; \ > +}) > > extern unsigned long riscv_v_vsize; > int riscv_v_setup_vsize(void); > @@ -40,39 +61,62 @@ static __always_inline bool has_vector(void) > return riscv_has_extension_unlikely(RISCV_ISA_EXT_v); > } > > +static __always_inline bool has_xtheadvector_no_alternatives(void) > +{ > + if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) > + return riscv_isa_vendor_extension_available(THEAD_VENDOR_= ID, XTHEADVECTOR); > + else > + return false; > +} > + > +static __always_inline bool has_xtheadvector(void) > +{ > + if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) > + return riscv_has_vendor_extension_unlikely(THEAD_VENDOR_I= D, > + RISCV_ISA_VEND= OR_EXT_XTHEADVECTOR); > + else > + return false; > +} > + > static inline void __riscv_v_vstate_clean(struct pt_regs *regs) > { > - regs->status =3D (regs->status & ~SR_VS) | SR_VS_CLEAN; > + regs->status =3D __riscv_v_vstate_or(regs->status, CLEAN); > } > > static inline void __riscv_v_vstate_dirty(struct pt_regs *regs) > { > - regs->status =3D (regs->status & ~SR_VS) | SR_VS_DIRTY; > + regs->status =3D __riscv_v_vstate_or(regs->status, DIRTY); > } > > static inline void riscv_v_vstate_off(struct pt_regs *regs) > { > - regs->status =3D (regs->status & ~SR_VS) | SR_VS_OFF; > + regs->status =3D __riscv_v_vstate_or(regs->status, OFF); > } > > static inline void riscv_v_vstate_on(struct pt_regs *regs) > { > - regs->status =3D (regs->status & ~SR_VS) | SR_VS_INITIAL; > + regs->status =3D __riscv_v_vstate_or(regs->status, INITIAL); > } > > static inline bool riscv_v_vstate_query(struct pt_regs *regs) > { > - return (regs->status & SR_VS) !=3D 0; > + return !__riscv_v_vstate_check(regs->status, OFF); > } > > static __always_inline void riscv_v_enable(void) > { > - csr_set(CSR_SSTATUS, SR_VS); > + if (has_xtheadvector()) > + csr_set(CSR_SSTATUS, SR_VS_THEAD); > + else > + csr_set(CSR_SSTATUS, SR_VS); > } > > static __always_inline void riscv_v_disable(void) > { > - csr_clear(CSR_SSTATUS, SR_VS); > + if (has_xtheadvector()) > + csr_clear(CSR_SSTATUS, SR_VS_THEAD); > + else > + csr_clear(CSR_SSTATUS, SR_VS); > } > > static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state= *dest) > @@ -81,10 +125,47 @@ static __always_inline void __vstate_csr_save(struct= __riscv_v_ext_state *dest) > "csrr %0, " __stringify(CSR_VSTART) "\n\t" > "csrr %1, " __stringify(CSR_VTYPE) "\n\t" > "csrr %2, " __stringify(CSR_VL) "\n\t" > - "csrr %3, " __stringify(CSR_VCSR) "\n\t" > - "csrr %4, " __stringify(CSR_VLENB) "\n\t" > : "=3Dr" (dest->vstart), "=3Dr" (dest->vtype), "=3Dr" (de= st->vl), > - "=3Dr" (dest->vcsr), "=3Dr" (dest->vlenb) : :); > + "=3Dr" (dest->vcsr) : :); > + > + if (has_xtheadvector()) { > + u32 tmp_vcsr; > + bool restore_fpu =3D false; > + unsigned long status =3D csr_read(CSR_SSTATUS); > + > + /* > + * CSR_VCSR is defined as > + * [2:1] - vxrm[1:0] > + * [0] - vxsat > + * The earlier vector spec implemented by T-Head uses sep= arate > + * registers for the same bit-elements, so just combine t= hose > + * into the existing output field. > + * > + * Additionally T-Head cores need FS to be enabled when a= ccessing > + * the VXRM and VXSAT CSRs, otherwise ending in illegal i= nstructions. > + * Though the cores do not implement the VXRM and VXSAT f= ields in the > + * FCSR CSR that vector-0.7.1 specifies. > + */ > + if ((status & SR_FS) =3D=3D SR_FS_OFF) { > + csr_set(CSR_SSTATUS, (status & ~SR_FS) | SR_FS_CL= EAN); > + restore_fpu =3D true; > + } > + > + asm volatile ( > + "csrr %[tmp_vcsr], " __stringify(VCSR_VXRM) "\n= \t" > + "slliw %[vcsr], %[tmp_vcsr], " __stringify(VCSR_= VXRM_SHIFT) "\n\t" > + "csrr %[tmp_vcsr], " __stringify(VCSR_VXSAT) "\= n\t" > + "or %[vcsr], %[vcsr], %[tmp_vcsr]\n\t" > + : [vcsr] "=3Dr" (dest->vcsr), [tmp_vcsr] "=3D&r" = (tmp_vcsr)); > + > + if (restore_fpu) > + csr_set(CSR_SSTATUS, status); vlenb is on ABI and ptrace needs that to recover the width of the register. So we should probably save Xtheadvector's vlenb into vstate if we meant to maintain ABI compatibility between V and Xtheadvector from the kernel. > + } else { > + asm volatile ( > + "csrr %[vcsr], " __stringify(CSR_VCSR) "\n\t" > + "csrr %[vlenb], " __stringify(CSR_VLENB) "\n\t" > + : [vcsr] "=3Dr" (dest->vcsr), [vlenb] "=3Dr" (des= t->vlenb)); > + } > } > > static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_st= ate *src) > @@ -95,9 +176,37 @@ static __always_inline void __vstate_csr_restore(stru= ct __riscv_v_ext_state *src > "vsetvl x0, %2, %1\n\t" > ".option pop\n\t" > "csrw " __stringify(CSR_VSTART) ", %0\n\t" > - "csrw " __stringify(CSR_VCSR) ", %3\n\t" > - : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl), > - "r" (src->vcsr) :); > + : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl)); > + > + if (has_xtheadvector()) { > + u32 tmp_vcsr; > + bool restore_fpu =3D false; > + unsigned long status =3D csr_read(CSR_SSTATUS); > + > + /* > + * Similar to __vstate_csr_save above, restore values for= the > + * separate VXRM and VXSAT CSRs from the vcsr variable. > + */ > + if ((status & SR_FS) =3D=3D SR_FS_OFF) { > + csr_set(CSR_SSTATUS, (status & ~SR_FS) | SR_FS_CL= EAN); > + restore_fpu =3D true; > + } > + > + asm volatile ( > + "srliw %[tmp_vcsr], %[vcsr], " __stringify(VCSR_= VXRM_SHIFT) "\n\t" > + "andi %[tmp_vcsr], %[tmp_vcsr], " __stringify(V= CSR_VXRM_MASK) "\n\t" > + "csrw " __stringify(VCSR_VXRM) ", %[tmp_vcsr]\n= \t" > + "andi %[tmp_vcsr], %[vcsr], " __stringify(VCSR_= VXSAT_MASK) "\n\t" > + "csrw " __stringify(VCSR_VXSAT) ", %[tmp_vcsr]\= n\t" > + : [tmp_vcsr] "=3D&r" (tmp_vcsr) : [vcsr] "r" (src= ->vcsr)); > + > + if (restore_fpu) > + csr_set(CSR_SSTATUS, status); > + } else { > + asm volatile ( > + "csrw " __stringify(CSR_VCSR) ", %[vcsr]\n\t" > + : : [vcsr] "r" (src->vcsr)); > + } > } > > static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *sav= e_to, > @@ -107,19 +216,33 @@ static inline void __riscv_v_vstate_save(struct __r= iscv_v_ext_state *save_to, > > riscv_v_enable(); > __vstate_csr_save(save_to); > - asm volatile ( > - ".option push\n\t" > - ".option arch, +v\n\t" > - "vsetvli %0, x0, e8, m8, ta, ma\n\t" > - "vse8.v v0, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vse8.v v8, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vse8.v v16, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vse8.v v24, (%1)\n\t" > - ".option pop\n\t" > - : "=3D&r" (vl) : "r" (datap) : "memory"); > + if (has_xtheadvector()) { > + asm volatile ( > + "mv t0, %0\n\t" > + THEAD_VSETVLI_T4X0E8M8D1 > + THEAD_VSB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VSB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VSB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VSB_V_V0T0 > + : : "r" (datap) : "memory", "t0", "t4"); > + } else { > + asm volatile ( > + ".option push\n\t" > + ".option arch, +v\n\t" > + "vsetvli %0, x0, e8, m8, ta, ma\n\t" > + "vse8.v v0, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vse8.v v8, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vse8.v v16, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vse8.v v24, (%1)\n\t" > + ".option pop\n\t" > + : "=3D&r" (vl) : "r" (datap) : "memory"); > + } > riscv_v_disable(); > } > > @@ -129,55 +252,77 @@ static inline void __riscv_v_vstate_restore(struct = __riscv_v_ext_state *restore_ > unsigned long vl; > > riscv_v_enable(); > - asm volatile ( > - ".option push\n\t" > - ".option arch, +v\n\t" > - "vsetvli %0, x0, e8, m8, ta, ma\n\t" > - "vle8.v v0, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vle8.v v8, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vle8.v v16, (%1)\n\t" > - "add %1, %1, %0\n\t" > - "vle8.v v24, (%1)\n\t" > - ".option pop\n\t" > - : "=3D&r" (vl) : "r" (datap) : "memory"); > + if (has_xtheadvector()) { > + asm volatile ( > + "mv t0, %0\n\t" > + THEAD_VSETVLI_T4X0E8M8D1 > + THEAD_VLB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VLB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VLB_V_V0T0 > + "add t0, t0, t4\n\t" > + THEAD_VLB_V_V0T0 > + : : "r" (datap) : "memory", "t0", "t4"); > + } else { > + asm volatile ( > + ".option push\n\t" > + ".option arch, +v\n\t" > + "vsetvli %0, x0, e8, m8, ta, ma\n\t" > + "vle8.v v0, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vle8.v v8, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vle8.v v16, (%1)\n\t" > + "add %1, %1, %0\n\t" > + "vle8.v v24, (%1)\n\t" > + ".option pop\n\t" > + : "=3D&r" (vl) : "r" (datap) : "memory"); > + } > __vstate_csr_restore(restore_from); > riscv_v_disable(); > } > > static inline void __riscv_v_vstate_discard(void) > { > - unsigned long vl, vtype_inval =3D 1UL << (BITS_PER_LONG - 1); > + unsigned long vtype_inval =3D 1UL << (BITS_PER_LONG - 1); > > riscv_v_enable(); > + if (has_xtheadvector()) > + asm volatile (THEAD_VSETVLI_X0X0E8M8D1); > + else > + asm volatile ( > + ".option push\n\t" > + ".option arch, +v\n\t" > + "vsetvli x0, x0, e8, m8, ta, ma\n\t" > + ".option pop\n\t"); > + > asm volatile ( > ".option push\n\t" > ".option arch, +v\n\t" > - "vsetvli %0, x0, e8, m8, ta, ma\n\t" > "vmv.v.i v0, -1\n\t" > "vmv.v.i v8, -1\n\t" > "vmv.v.i v16, -1\n\t" > "vmv.v.i v24, -1\n\t" > - "vsetvl %0, x0, %1\n\t" > + "vsetvl x0, x0, %0\n\t" > ".option pop\n\t" > - : "=3D&r" (vl) : "r" (vtype_inval) : "memory"); > + : : "r" (vtype_inval)); > + > riscv_v_disable(); > } > > static inline void riscv_v_vstate_discard(struct pt_regs *regs) > { > - if ((regs->status & SR_VS) =3D=3D SR_VS_OFF) > - return; > - > - __riscv_v_vstate_discard(); > - __riscv_v_vstate_dirty(regs); > + if (riscv_v_vstate_query(regs)) { > + __riscv_v_vstate_discard(); > + __riscv_v_vstate_dirty(regs); > + } > } > > static inline void riscv_v_vstate_save(struct __riscv_v_ext_state *vstat= e, > struct pt_regs *regs) > { > - if ((regs->status & SR_VS) =3D=3D SR_VS_DIRTY) { > + if (__riscv_v_vstate_check(regs->status, DIRTY)) { > __riscv_v_vstate_save(vstate, vstate->datap); > __riscv_v_vstate_clean(regs); > } > @@ -186,7 +331,7 @@ static inline void riscv_v_vstate_save(struct __riscv= _v_ext_state *vstate, > static inline void riscv_v_vstate_restore(struct __riscv_v_ext_state *vs= tate, > struct pt_regs *regs) > { > - if ((regs->status & SR_VS) !=3D SR_VS_OFF) { > + if (riscv_v_vstate_query(regs)) { > __riscv_v_vstate_restore(vstate, vstate->datap); > __riscv_v_vstate_clean(regs); > } > @@ -195,7 +340,7 @@ static inline void riscv_v_vstate_restore(struct __ri= scv_v_ext_state *vstate, > static inline void riscv_v_vstate_set_restore(struct task_struct *task, > struct pt_regs *regs) > { > - if ((regs->status & SR_VS) !=3D SR_VS_OFF) { > + if (riscv_v_vstate_query(regs)) { > set_tsk_thread_flag(task, TIF_RISCV_V_DEFER_RESTORE); > riscv_v_vstate_on(regs); > } > diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeatur= e.c > index 2993318b8ea2..44f0017a98d5 100644 > --- a/arch/riscv/kernel/cpufeature.c > +++ b/arch/riscv/kernel/cpufeature.c > @@ -781,7 +781,7 @@ void __init riscv_fill_hwcap(void) > elf_hwcap &=3D ~COMPAT_HWCAP_ISA_F; > } > > - if (elf_hwcap & COMPAT_HWCAP_ISA_V) { > + if (elf_hwcap & COMPAT_HWCAP_ISA_V || has_xtheadvector_no_alterna= tives()) { > riscv_v_setup_vsize(); > /* > * ISA string in device tree might have 'v' flag, but > diff --git a/arch/riscv/kernel/kernel_mode_vector.c b/arch/riscv/kernel/k= ernel_mode_vector.c > index 6afe80c7f03a..99972a48e86b 100644 > --- a/arch/riscv/kernel/kernel_mode_vector.c > +++ b/arch/riscv/kernel/kernel_mode_vector.c > @@ -143,7 +143,7 @@ static int riscv_v_start_kernel_context(bool *is_nest= ed) > > /* Transfer the ownership of V from user to kernel, then save */ > riscv_v_start(RISCV_PREEMPT_V | RISCV_PREEMPT_V_DIRTY); > - if ((task_pt_regs(current)->status & SR_VS) =3D=3D SR_VS_DIRTY) { > + if (__riscv_v_vstate_check(task_pt_regs(current)->status, DIRTY))= { > uvstate =3D ¤t->thread.vstate; > __riscv_v_vstate_save(uvstate, uvstate->datap); > } > @@ -160,7 +160,7 @@ asmlinkage void riscv_v_context_nesting_start(struct = pt_regs *regs) > return; > > depth =3D riscv_v_ctx_get_depth(); > - if (depth =3D=3D 0 && (regs->status & SR_VS) =3D=3D SR_VS_DIRTY) > + if (depth =3D=3D 0 && __riscv_v_vstate_check(regs->status, DIRTY)= ) > riscv_preempt_v_set_dirty(); > > riscv_v_ctx_depth_inc(); > @@ -208,7 +208,7 @@ void kernel_vector_begin(void) > { > bool nested =3D false; > > - if (WARN_ON(!has_vector())) > + if (WARN_ON(!(has_vector() || has_xtheadvector()))) > return; > > BUG_ON(!may_use_simd()); > @@ -236,7 +236,7 @@ EXPORT_SYMBOL_GPL(kernel_vector_begin); > */ > void kernel_vector_end(void) > { > - if (WARN_ON(!has_vector())) > + if (WARN_ON(!(has_vector() || has_xtheadvector()))) > return; > > riscv_v_disable(); > diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c > index 92922dbd5b5c..eabca86fc3c0 100644 > --- a/arch/riscv/kernel/process.c > +++ b/arch/riscv/kernel/process.c > @@ -178,7 +178,7 @@ void flush_thread(void) > void arch_release_task_struct(struct task_struct *tsk) > { > /* Free the vector context of datap. */ > - if (has_vector()) > + if (has_vector() || has_xtheadvector()) > riscv_v_thread_free(tsk); > } > > @@ -225,7 +225,7 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) > p->thread.s[0] =3D 0; > } > p->thread.riscv_v_flags =3D 0; > - if (has_vector()) > + if (has_vector() || has_xtheadvector()) > riscv_v_thread_alloc(p); > p->thread.ra =3D (unsigned long)ret_from_fork; > p->thread.sp =3D (unsigned long)childregs; /* kernel sp */ > diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c > index 501e66debf69..5d3ba8e46807 100644 > --- a/arch/riscv/kernel/signal.c > +++ b/arch/riscv/kernel/signal.c > @@ -188,7 +188,7 @@ static long restore_sigcontext(struct pt_regs *regs, > > return 0; > case RISCV_V_MAGIC: > - if (!has_vector() || !riscv_v_vstate_query(regs) = || > + if (!(has_vector() || has_xtheadvector()) || !ris= cv_v_vstate_query(regs) || > size !=3D riscv_v_sc_size) > return -EINVAL; > > @@ -210,7 +210,7 @@ static size_t get_rt_frame_size(bool cal_all) > > frame_size =3D sizeof(*frame); > > - if (has_vector()) { > + if (has_vector() || has_xtheadvector()) { > if (cal_all || riscv_v_vstate_query(task_pt_regs(current)= )) > total_context_size +=3D riscv_v_sc_size; > } > @@ -283,7 +283,7 @@ static long setup_sigcontext(struct rt_sigframe __use= r *frame, > if (has_fpu()) > err |=3D save_fp_state(regs, &sc->sc_fpregs); > /* Save the vector state. */ > - if (has_vector() && riscv_v_vstate_query(regs)) > + if ((has_vector() || has_xtheadvector()) && riscv_v_vstate_query(= regs)) > err |=3D save_v_state(regs, (void __user **)&sc_ext_ptr); > /* Write zero to fp-reserved space and check it on restore_sigcon= text */ > err |=3D __put_user(0, &sc->sc_extdesc.reserved); > diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c > index e04586cdb7f0..c12ea4547da6 100644 > --- a/arch/riscv/kernel/vector.c > +++ b/arch/riscv/kernel/vector.c > @@ -63,7 +63,7 @@ int riscv_v_setup_vsize(void) > > void __init riscv_v_setup_ctx_cache(void) > { > - if (!has_vector()) > + if (!(has_vector() || has_xtheadvector())) > return; > > riscv_v_user_cachep =3D kmem_cache_create_usercopy("riscv_vector_= ctx", > @@ -184,7 +184,8 @@ bool riscv_v_first_use_handler(struct pt_regs *regs) > u32 insn =3D (u32)regs->badaddr; > > /* Do not handle if V is not supported, or disabled */ > - if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V)) > + if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V) && > + !(has_xtheadvector() && riscv_v_vstate_ctrl_user_allowed())) > return false; > > /* If V has been enabled then it is not the first-use trap */ > @@ -223,7 +224,7 @@ void riscv_v_vstate_ctrl_init(struct task_struct *tsk= ) > bool inherit; > int cur, next; > > - if (!has_vector()) > + if (!(has_vector() || has_xtheadvector())) > return; > > next =3D riscv_v_ctrl_get_next(tsk); > @@ -245,7 +246,7 @@ void riscv_v_vstate_ctrl_init(struct task_struct *tsk= ) > > long riscv_v_vstate_ctrl_get_current(void) > { > - if (!has_vector()) > + if (!(has_vector() || has_xtheadvector())) > return -EINVAL; > > return current->thread.vstate_ctrl & PR_RISCV_V_VSTATE_CTRL_MASK; > @@ -256,7 +257,7 @@ long riscv_v_vstate_ctrl_set_current(unsigned long ar= g) > bool inherit; > int cur, next; > > - if (!has_vector()) > + if (!(has_vector() || has_xtheadvector())) > return -EINVAL; > > if (arg & ~PR_RISCV_V_VSTATE_CTRL_MASK) > @@ -306,7 +307,7 @@ static struct ctl_table riscv_v_default_vstate_table[= ] =3D { > > static int __init riscv_v_sysctl_init(void) > { > - if (has_vector()) > + if (has_vector() || has_xtheadvector()) > if (!register_sysctl("abi", riscv_v_default_vstate_table)= ) > return -EINVAL; > return 0; > > -- > 2.44.0 > > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv Cheers, Andy