lkml.org 
[lkml]   [2019]   [Dec]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v10 02/19] RISC-V: Add bitmap reprensenting ISA features common across CPUs
    Date
    This patch adds riscv_isa bitmap which represents Host ISA features
    common across all Host CPUs. The riscv_isa is not same as elf_hwcap
    because elf_hwcap will only have ISA features relevant for user-space
    apps whereas riscv_isa will have ISA features relevant to both kernel
    and user-space apps.

    One of the use-case for riscv_isa bitmap is in KVM hypervisor where
    we will use it to do following operations:

    1. Check whether hypervisor extension is available
    2. Find ISA features that need to be virtualized (e.g. floating
    point support, vector extension, etc.)

    Signed-off-by: Anup Patel <anup.patel@wdc.com>
    Signed-off-by: Atish Patra <atish.patra@wdc.com>
    Reviewed-by: Alexander Graf <graf@amazon.com>
    ---
    arch/riscv/include/asm/hwcap.h | 22 +++++++++
    arch/riscv/kernel/cpufeature.c | 83 ++++++++++++++++++++++++++++++++--
    2 files changed, 102 insertions(+), 3 deletions(-)

    diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
    index 1bb0cd04aec3..5589c012e004 100644
    --- a/arch/riscv/include/asm/hwcap.h
    +++ b/arch/riscv/include/asm/hwcap.h
    @@ -8,6 +8,7 @@
    #ifndef _ASM_RISCV_HWCAP_H
    #define _ASM_RISCV_HWCAP_H

    +#include <linux/bits.h>
    #include <uapi/asm/hwcap.h>

    #ifndef __ASSEMBLY__
    @@ -22,6 +23,27 @@ enum {
    };

    extern unsigned long elf_hwcap;
    +
    +#define RISCV_ISA_EXT_a ('a' - 'a')
    +#define RISCV_ISA_EXT_c ('c' - 'a')
    +#define RISCV_ISA_EXT_d ('d' - 'a')
    +#define RISCV_ISA_EXT_f ('f' - 'a')
    +#define RISCV_ISA_EXT_h ('h' - 'a')
    +#define RISCV_ISA_EXT_i ('i' - 'a')
    +#define RISCV_ISA_EXT_m ('m' - 'a')
    +#define RISCV_ISA_EXT_s ('s' - 'a')
    +#define RISCV_ISA_EXT_u ('u' - 'a')
    +
    +#define RISCV_ISA_EXT_MAX 256
    +
    +unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
    +
    +#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
    +
    +bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
    +#define riscv_isa_extension_available(isa_bitmap, ext) \
    + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
    +
    #endif

    #endif /* _ASM_RISCV_HWCAP_H */
    diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
    index 0b40705567b7..e172a2322b34 100644
    --- a/arch/riscv/kernel/cpufeature.c
    +++ b/arch/riscv/kernel/cpufeature.c
    @@ -6,6 +6,7 @@
    * Copyright (C) 2017 SiFive
    */

    +#include <linux/bitmap.h>
    #include <linux/of.h>
    #include <asm/processor.h>
    #include <asm/hwcap.h>
    @@ -13,15 +14,57 @@
    #include <asm/switch_to.h>

    unsigned long elf_hwcap __read_mostly;
    +
    +/* Host ISA bitmap */
    +static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
    +
    #ifdef CONFIG_FPU
    bool has_fpu __read_mostly;
    #endif

    +/**
    + * riscv_isa_extension_base() - Get base extension word
    + *
    + * @isa_bitmap: ISA bitmap to use
    + * Return: base extension word as unsigned long value
    + *
    + * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
    + */
    +unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap)
    +{
    + if (!isa_bitmap)
    + return riscv_isa[0];
    + return isa_bitmap[0];
    +}
    +EXPORT_SYMBOL_GPL(riscv_isa_extension_base);
    +
    +/**
    + * __riscv_isa_extension_available() - Check whether given extension
    + * is available or not
    + *
    + * @isa_bitmap: ISA bitmap to use
    + * @bit: bit position of the desired extension
    + * Return: true or false
    + *
    + * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
    + */
    +bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit)
    +{
    + const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa;
    +
    + if (bit >= RISCV_ISA_EXT_MAX)
    + return false;
    +
    + return test_bit(bit, bmap) ? true : false;
    +}
    +EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
    +
    void riscv_fill_hwcap(void)
    {
    struct device_node *node;
    const char *isa;
    - size_t i;
    + char print_str[BITS_PER_LONG + 1];
    + size_t i, j, isa_len;
    static unsigned long isa2hwcap[256] = {0};

    isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
    @@ -33,8 +76,11 @@ void riscv_fill_hwcap(void)

    elf_hwcap = 0;

    + bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
    +
    for_each_of_cpu_node(node) {
    unsigned long this_hwcap = 0;
    + unsigned long this_isa = 0;

    if (riscv_of_processor_hartid(node) < 0)
    continue;
    @@ -42,8 +88,24 @@ void riscv_fill_hwcap(void)
    if (riscv_read_check_isa(node, &isa) < 0)
    continue;

    - for (i = 0; i < strlen(isa); ++i)
    + i = 0;
    + isa_len = strlen(isa);
    +#if IS_ENABLED(CONFIG_32BIT)
    + if (!strncmp(isa, "rv32", 4))
    + i += 4;
    +#elif IS_ENABLED(CONFIG_64BIT)
    + if (!strncmp(isa, "rv64", 4))
    + i += 4;
    +#endif
    + for (; i < isa_len; ++i) {
    this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
    + /*
    + * TODO: X, Y and Z extension parsing for Host ISA
    + * bitmap will be added in-future.
    + */
    + if ('a' <= isa[i] && isa[i] < 'x')
    + this_isa |= (1UL << (isa[i] - 'a'));
    + }

    /*
    * All "okay" hart should have same isa. Set HWCAP based on
    @@ -54,6 +116,11 @@ void riscv_fill_hwcap(void)
    elf_hwcap &= this_hwcap;
    else
    elf_hwcap = this_hwcap;
    +
    + if (riscv_isa[0])
    + riscv_isa[0] &= this_isa;
    + else
    + riscv_isa[0] = this_isa;
    }

    /* We don't support systems with F but without D, so mask those out
    @@ -63,7 +130,17 @@ void riscv_fill_hwcap(void)
    elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
    }

    - pr_info("elf_hwcap is 0x%lx\n", elf_hwcap);
    + memset(print_str, 0, sizeof(print_str));
    + for (i = 0, j = 0; i < BITS_PER_LONG; i++)
    + if (riscv_isa[0] & BIT_MASK(i))
    + print_str[j++] = (char)('a' + i);
    + pr_info("riscv: ISA extensions %s\n", print_str);
    +
    + memset(print_str, 0, sizeof(print_str));
    + for (i = 0, j = 0; i < BITS_PER_LONG; i++)
    + if (elf_hwcap & BIT_MASK(i))
    + print_str[j++] = (char)('a' + i);
    + pr_info("riscv: ELF capabilities %s\n", print_str);

    #ifdef CONFIG_FPU
    if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
    --
    2.17.1
    \
     
     \ /
      Last update: 2019-12-23 12:36    [W:4.078 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site