riscv: vector: use kmem_cache to manage vector context
authorAndy Chiu <andy.chiu@sifive.com>
Mon, 15 Jan 2024 05:59:28 +0000 (05:59 +0000)
committerPalmer Dabbelt <palmer@rivosinc.com>
Tue, 16 Jan 2024 15:14:01 +0000 (07:14 -0800)
The allocation size of thread.vstate.datap is always riscv_v_vsize. So
it is possbile to use kmem_cache_* to manage the allocation. This gives
users more information regarding allocation of vector context via
/proc/slabinfo. And it potentially reduces the latency of the first-use
trap because of the allocation caches.

Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20240115055929.4736-10-andy.chiu@sifive.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/vector.h
arch/riscv/kernel/process.c
arch/riscv/kernel/vector.c

index d7507952062999f25d234ad39f71dcd8aa39dc46..7b316050f24f7e7f3b85bdc15798d3a131f5d517 100644 (file)
@@ -26,6 +26,8 @@ void kernel_vector_begin(void);
 void kernel_vector_end(void);
 void get_cpu_vector_context(void);
 void put_cpu_vector_context(void);
+void riscv_v_thread_free(struct task_struct *tsk);
+void __init riscv_v_setup_ctx_cache(void);
 
 static inline u32 riscv_v_flags(void)
 {
@@ -227,6 +229,8 @@ static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
 #define __switch_to_vector(__prev, __next)     do {} while (0)
 #define riscv_v_vstate_off(regs)               do {} while (0)
 #define riscv_v_vstate_on(regs)                        do {} while (0)
+#define riscv_v_thread_free(tsk)               do {} while (0)
+#define  riscv_v_setup_ctx_cache()             do {} while (0)
 
 #endif /* CONFIG_RISCV_ISA_V */
 
index 36993f408de4a45d16787771eb831da434371f1d..862d59c3872e2e31bffb1d4d49fde783223817a4 100644 (file)
@@ -179,7 +179,7 @@ void arch_release_task_struct(struct task_struct *tsk)
 {
        /* Free the vector context of datap. */
        if (has_vector())
-               kfree(tsk->thread.vstate.datap);
+               riscv_v_thread_free(tsk);
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
@@ -228,3 +228,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
        p->thread.sp = (unsigned long)childregs; /* kernel sp */
        return 0;
 }
+
+void __init arch_task_cache_init(void)
+{
+       riscv_v_setup_ctx_cache();
+}
index c1f28bc89ec64b8973c12330fe40cab3d79e304a..f7b4aeb9e45794f47ee3f0177d75994c965a2be1 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/bug.h>
 
 static bool riscv_v_implicit_uacc = IS_ENABLED(CONFIG_RISCV_ISA_V_DEFAULT_ENABLE);
+static struct kmem_cache *riscv_v_user_cachep;
 
 unsigned long riscv_v_vsize __read_mostly;
 EXPORT_SYMBOL_GPL(riscv_v_vsize);
@@ -47,6 +48,16 @@ int riscv_v_setup_vsize(void)
        return 0;
 }
 
+void __init riscv_v_setup_ctx_cache(void)
+{
+       if (!has_vector())
+               return;
+
+       riscv_v_user_cachep = kmem_cache_create_usercopy("riscv_vector_ctx",
+                                                        riscv_v_vsize, 16, SLAB_PANIC,
+                                                        0, riscv_v_vsize, NULL);
+}
+
 static bool insn_is_vector(u32 insn_buf)
 {
        u32 opcode = insn_buf & __INSN_OPCODE_MASK;
@@ -84,7 +95,7 @@ static int riscv_v_thread_zalloc(void)
 {
        void *datap;
 
-       datap = kzalloc(riscv_v_vsize, GFP_KERNEL);
+       datap = kmem_cache_zalloc(riscv_v_user_cachep, GFP_KERNEL);
        if (!datap)
                return -ENOMEM;
 
@@ -94,6 +105,12 @@ static int riscv_v_thread_zalloc(void)
        return 0;
 }
 
+void riscv_v_thread_free(struct task_struct *tsk)
+{
+       if (tsk->thread.vstate.datap)
+               kmem_cache_free(riscv_v_user_cachep, tsk->thread.vstate.datap);
+}
+
 #define VSTATE_CTRL_GET_CUR(x) ((x) & PR_RISCV_V_VSTATE_CTRL_CUR_MASK)
 #define VSTATE_CTRL_GET_NEXT(x) (((x) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) >> 2)
 #define VSTATE_CTRL_MAKE_NEXT(x) (((x) << 2) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK)