#include <uapi/asm/hwcap.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/jump_label.h>
 /*
  * This yields a mask that user programs can use to figure out what
  * instruction set this cpu supports.
        RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
 };
 
+/*
+ * This enum represents the logical ID for each RISC-V ISA extension static
+ * keys. We can use static key to optimize code path if some ISA extensions
+ * are available.
+ */
+enum riscv_isa_ext_key {
+       RISCV_ISA_EXT_KEY_FPU,          /* For 'F' and 'D' */
+       RISCV_ISA_EXT_KEY_MAX,
+};
+
 struct riscv_isa_ext_data {
        /* Name of the extension displayed to userspace via /proc/cpuinfo */
        char uprop[RISCV_ISA_EXT_NAME_LEN_MAX];
        unsigned int isa_ext_id;
 };
 
+extern struct static_key_false riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_MAX];
+
+static __always_inline int riscv_isa_ext2key(int num)
+{
+       switch (num) {
+       case RISCV_ISA_EXT_f:
+               return RISCV_ISA_EXT_KEY_FPU;
+       case RISCV_ISA_EXT_d:
+               return RISCV_ISA_EXT_KEY_FPU;
+       default:
+               return -EINVAL;
+       }
+}
+
 unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
 
 #define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
 
 #ifdef CONFIG_FPU
 __ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);
 #endif
+__ro_after_init DEFINE_STATIC_KEY_ARRAY_FALSE(riscv_isa_ext_keys, RISCV_ISA_EXT_KEY_MAX);
+EXPORT_SYMBOL(riscv_isa_ext_keys);
 
 /**
  * riscv_isa_extension_base() - Get base extension word
                        print_str[j++] = (char)('a' + i);
        pr_info("riscv: ELF capabilities %s\n", print_str);
 
+       for_each_set_bit(i, riscv_isa, RISCV_ISA_EXT_MAX) {
+               j = riscv_isa_ext2key(i);
+               if (j >= 0)
+                       static_branch_enable(&riscv_isa_ext_keys[j]);
+       }
 #ifdef CONFIG_FPU
        if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
                static_branch_enable(&cpu_hwcap_fpu);