openeuler-riscv / oerv-team

OERV 实习生工作中心
11 stars 42 forks source link

Kernel: Backport full riscv_hwprobe syscall support to 6.6 #909

Open wzssyqa opened 3 months ago

wzssyqa commented 3 months ago

To work with glibc-hwcaps, we need full support riscv_hwprobe syscall.

Kernel 6.10 has more macro etc support.

Let's port it to 6.6.

wzssyqa commented 3 months ago

hwprobe-6.11-to-6.6.diff.gz

无脑盲backport,能编译过,能不能跑还不知道。

Jer6y commented 3 months ago

riscv hwprobe syscall backport报告

Linux hwprobe syscall 总览

syscall作用

syscall用户态使用方法

Linux 6.10 的 riscv hwprobe syscall 支持的功能

具体的可参考文档链接 : https://docs.kernel.org/arch/riscv/hwprobe.html

OLK6.6 hwprobe syscall compare to Linux 6.10 riscv hwprobe syscall

  1. 功能 : 获取 Zicboz 扩展的 block size 缺失
  2. 功能 : 获取硬件支持的 ISA 扩展 不完善,已经多了很多的扩展 [这个与用户态可以做的优化紧密相关]
  3. 功能 : flag 属性 RISCV_HWPROBE_WHICH_CPUS 缺失

diff 文件 hwprobe-6.11-to-6.6.diff.gz 存在的问题

总体情况 , backport 的内容比较激进,除了 backport hwprobe syscall 需要的内容,还把很多与 cpufeature 相关的内容进行了 backport

目前找到的存在的问题

  1. 与宏 "CONFIG_RISCV_MISALIGNED" 有关的函数 backport 下来了,但是对应的 Kbuild 系统里面的实现没有 backport 【这个与 hwprobe "通过 hwprobe syscall 获取硬件支持的与性能有关的信息的位图 " 有关,在这个功能上就无法获得对应的情况,会始终获得 “RISCV_HWPROBE_MISALIGNED_UNKNOWN”
  2. 同理,CONFIG_RISCV_PROBE_UNALIGNED_ACCESS 宏也类似,也是与hwprobe 的这个功能有关

本次 backport 的内容

目前backport 了一版改动相较于 原来老师的bakcport 的 较小的版本,牵涉到的文件有

arc/riscv/include/asm/hwcap.h

arch/riscv/include/asm/hwprobe.h

arch/riscv/include/asm/sbi.h

arch/riscv/include/uapi/asm/hwprobe.h

arch/riscvkernel/cpu.c

arch/riscv/kernel/cpufeature.c

arch/riscv/kernel/sys_riscv.c

arch/riscv/kernel/vdso/hwprobe.c

backport 完成的测试方法

目前可以通过编译,但是未进行测试,目前想到的测试方法有如下

用户态 syscall 获取信息

通过用户态的syscall ,把hwporbe 相关的所有功能进行测试获取信息,并进行记录

内核态设备调用函数获取信息进行 match

写内核态的模块,直接调用 hwprobe 提供的对应的内核开发的接口,获取信息,记录和用户态是否一致

opensbi 输出进行对比

像 mvendorid, marchid 这种寄存器的值,可以以 opensbi的输出为标准线,check 内核态的接口调用是否正常,用户态syscall 是否正常

Jer6y commented 3 months ago

内核态BackPort 后的测试代码

主要是测试了backport 修改的所有的 api 函数

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/hwprobe.h>
#include <asm/hwcap.h>
#include <linux/printk.h>
#include <linux/random.h>
#include <asm/sbi.h>
#include <linux/smp.h>

typedef void (*test_func_t)(int* err, int* success);

struct test_single_kit {
    const char* name;
    test_func_t test_handler;
};

#define CHECK_TEST_FUNC_T_PARAMETER() do { if(err == NULL || success == NULL) { pr_err("error paramter for  test"); return; } } while(0)

static void test_riscv_hwprobe_key_is_valid(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    bool ret;
    //test for valid
    for(int i=0;i<=RISCV_HWPROBE_MAX_KEY;i++)
    {
        ret = riscv_hwprobe_key_is_valid(i);
        if(ret == true)
            (*success)++;
        else 
        {
            (*err)++;
            pr_err("error %d ret %d\n", i, ret);
        }

    }

    //test for invalid
    for(int i=0;i<=7000;i++)
    {
        __s64 random;
        random = (__s64)get_random_u64();
        if(random >=0 && random <= RISCV_HWPROBE_MAX_KEY)
            continue;
        ret = riscv_hwprobe_key_is_valid((__s64)random);
        if(ret == false)
            (*success)++;
        else
        {
            (*err)++;
            pr_err("error occur when test hwprobe_key_is_valid %d \n",random);
        }
    }
}

static void test_hwprobe_key_is_bitmask(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    bool ret;
    // test for valid
    for(int i=0;i<=RISCV_HWPROBE_MAX_KEY;i++)
    {
        if(i == RISCV_HWPROBE_KEY_BASE_BEHAVIOR || i == RISCV_HWPROBE_KEY_IMA_EXT_0 || i == RISCV_HWPROBE_KEY_CPUPERF_0)
        {
            ret = hwprobe_key_is_bitmask(i);
            if(ret == true)
                (*success)++;
            else
            {
                (*err)++;
                pr_err("occur error when test_hwprobe_key_is_bitmask %d\n", i);
            }

        }
    }
    // test for invalid
    for(int i=0;i<=5000;i++)
    {
        if(i == RISCV_HWPROBE_KEY_BASE_BEHAVIOR || i == RISCV_HWPROBE_KEY_IMA_EXT_0 || i == RISCV_HWPROBE_KEY_CPUPERF_0)
            continue;
        ret = hwprobe_key_is_bitmask(i);
        if(ret == false)
            (*success)++;
        else
        {
            (*err)++;
            pr_err("occur error when test_hwprobe_key_is_bitmask %d\n", i);
        }       
    }
}

static void test_riscv_hwprobe_pair_cmp(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    bool ret;
    struct riscv_hwprobe cmp1;
    struct riscv_hwprobe cmp2;
    //test for the same
    //test for the key valid and invalid
    for(int i=0;i<=RISCV_HWPROBE_MAX_KEY + 5000;i++)
    {
        cmp1.key = i;
        cmp2.key = i;
        //special key <=> bitmask
        if(i == RISCV_HWPROBE_KEY_BASE_BEHAVIOR || i == RISCV_HWPROBE_KEY_IMA_EXT_0 || i == RISCV_HWPROBE_KEY_CPUPERF_0)
        {
                //test for the same bit map
                __s64 random = (__s64)get_random_u64();
                cmp1.value = random;
                cmp2.value = random;
                ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
                if(ret == true)
                    (*success)++;
                else
                    (*err)++;
                //test for cmp1 bitmap >= cmp2 bitmap 
                int bit_1 = (int)(get_random_u8() % 64);
                int bit_2 = (int)(get_random_u8() % 64);
                int bit_3 = (int)(get_random_u8() % 64);
                int bit_4 = (int)(get_random_u8() % 64);
                int bit_5 = (int)(get_random_u8() % 64);
                int bit_6 = (int)(get_random_u8() % 64);
                cmp1.value &= (~(1<<bit_1));
                cmp2.value &= (~(1<<bit_1));
                cmp1.value |= (1<<bit_1);
                ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
                if(ret == true)
                    (*success)++;
                else
                    (*err)++;

                cmp1.value &= (~((1<<bit_2) | (1<<bit_3)));
                cmp2.value &= (~((1<<bit_2) | (1<<bit_3)));
                cmp1.value |= ((1<<bit_2) | (1<<bit_3));
                ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
                if(ret == true)
                    (*success)++;
                else
                    (*err)++;

                cmp1.value &= (~((1<<bit_4) | (1<<bit_5) | (1<<bit_6)));
                cmp2.value &= (~((1<<bit_4) | (1<<bit_5) | (1<<bit_6)));
                cmp1.value |= ((1<<bit_4) | (1<<bit_5) | (1<<bit_6));
                ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
                if(ret == true)
                    (*success)++;
                else
                    (*err)++;
        }
        else
        {
            __s64 random = (__s64)get_random_u64();
            cmp1.value = random;
            cmp2.value = random;
            ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
            if(ret == true)
                (*success)++;
            else
                (*err)++;
        }
    }
    //test for not the same
    for(int i=0;i<=RISCV_HWPROBE_MAX_KEY + 5000;i++)
    {
        cmp1.key = i;
        cmp2.key = i + 1 + (__s64)((__u64)get_random_u16());
        ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
        if(ret == false)
            (*success)++;
        else
            (*err)++;

        cmp1.key = i;
        cmp2.key = i;
        if(i == RISCV_HWPROBE_KEY_BASE_BEHAVIOR || i == RISCV_HWPROBE_KEY_IMA_EXT_0 || i == RISCV_HWPROBE_KEY_CPUPERF_0)
        {
            //test for cmp1 bitmap >= cmp2 bitmap 
            int bit_1 = (int)(get_random_u8() % 64);
            int bit_2 = (int)(get_random_u8() % 64);
            int bit_3 = (int)(get_random_u8() % 64);
            cmp1.value = (__s64)(get_random_u64());
            cmp2.value = cmp1.value;

            cmp1.value &= (~(1<<bit_1));
            cmp2.value &= (~(1<<bit_1));
            cmp2.value |= (1<<bit_1);
            ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
            if(ret == false)
                (*success)++;
            else
                (*err)++;

            cmp1.value &= (~((1<<bit_2) | (1<<bit_3)));
            cmp2.value &= (~((1<<bit_2) | (1<<bit_3)));
            cmp2.value |= ((1<<bit_2) | (1<<bit_3));
            ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
            if(ret == false)
                (*success)++;
            else
                (*err)++;
        }
        else
        {
            cmp1.value = i;
            cmp2.value = i + 1 + (__s64)((__u64)get_random_u16());
            ret = riscv_hwprobe_pair_cmp(&cmp1, &cmp2);
            if(ret == false)
                (*success)++;
            else
                (*err)++;
        }
    }

}
static void test_riscv_isa_extension_base(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
#undef  CHECK_EXTENSION
#define CHECK_EXTENSION(x) do { if(base_isa & (1 << RISCV_ISA_EXT_##x)) { (*success)++; pr_info("support RISCV_ISA_" #x "\n"); } else { (*err)++; pr_info("base extension RISCV_ISA_" #x " not support!\n"); } } while(0)
    unsigned long base_isa = riscv_isa_extension_base(NULL);
    CHECK_EXTENSION(a);
    CHECK_EXTENSION(c);
    CHECK_EXTENSION(d);
    CHECK_EXTENSION(f);
    CHECK_EXTENSION(h);
    CHECK_EXTENSION(i);
    CHECK_EXTENSION(m);
    CHECK_EXTENSION(q);
    CHECK_EXTENSION(v);
}

// static void test_riscv_get_elf_hwcap(int* err, int* success)
// {
//     CHECK_TEST_FUNC_T_PARAMETER();
// #undef  CHECK_EXTENSION
// #define CHECK_EXTENSION(x) do { if(elf_isa_cap & (1 << RISCV_ISA_EXT_##x)) { (*success)++; pr_info("elf extension RISCV_ISA_" #x " support\n"); } else { (*err)++; pr_info("elf extension RISCV_ISA_" #x " not support!\n"); } } while(0)
//     unsigned long elf_isa_cap = riscv_get_elf_hwcap();
//     CHECK_EXTENSION(a);
//     CHECK_EXTENSION(c);
//     CHECK_EXTENSION(d);
//     CHECK_EXTENSION(f);
//     CHECK_EXTENSION(h);
//     CHECK_EXTENSION(i);
//     CHECK_EXTENSION(m);
//     CHECK_EXTENSION(q);
//     CHECK_EXTENSION(v);

// }

static void test_riscv_isa_available(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
#undef  CHECK_EXTENSION
#define CHECK_EXTENSION(x) do { (*success)++; if(riscv_isa_extension_available(NULL, x)) { pr_info("extension RISCV_ISA_" #x " support\n"); } else { pr_info("extension RISCV_ISA_" #x " not support\n"); } } while(0)
    CHECK_EXTENSION(a);
    CHECK_EXTENSION(c);
    CHECK_EXTENSION(d);
    CHECK_EXTENSION(f);
    CHECK_EXTENSION(h);
    CHECK_EXTENSION(i);
    CHECK_EXTENSION(m);
    CHECK_EXTENSION(q);
    CHECK_EXTENSION(v);
    CHECK_EXTENSION(SSCOFPMF);
    CHECK_EXTENSION(SSTC);
    CHECK_EXTENSION(SVINVAL);
    CHECK_EXTENSION(SVPBMT);
    CHECK_EXTENSION(ZBB);
    CHECK_EXTENSION(ZICBOM);
    CHECK_EXTENSION(ZIHINTPAUSE);
    CHECK_EXTENSION(SVNAPOT);
    CHECK_EXTENSION(ZICBOZ);
    CHECK_EXTENSION(SMAIA);
    CHECK_EXTENSION(SSAIA);
    CHECK_EXTENSION(ZBA);
    CHECK_EXTENSION(ZBS);
    CHECK_EXTENSION(ZICNTR);
    CHECK_EXTENSION(ZICSR);
    CHECK_EXTENSION(ZIFENCEI);
    CHECK_EXTENSION(ZIHPM);
    CHECK_EXTENSION(SMSTATEEN);
    CHECK_EXTENSION(ZICOND);
    CHECK_EXTENSION(ZBC);
    CHECK_EXTENSION(ZBKB);
    CHECK_EXTENSION(ZBKC);
    CHECK_EXTENSION(ZBKX);
    CHECK_EXTENSION(ZKND);
    CHECK_EXTENSION(ZKNE);
    CHECK_EXTENSION(ZKNH);
    CHECK_EXTENSION(ZKR);
    CHECK_EXTENSION(ZKSED);
    CHECK_EXTENSION(ZKSH);
    CHECK_EXTENSION(ZKT);
    CHECK_EXTENSION(ZVBB);
    CHECK_EXTENSION(ZVBC);
    CHECK_EXTENSION(ZVKB);
    CHECK_EXTENSION(ZVKG);
    CHECK_EXTENSION(ZVKNED);
    CHECK_EXTENSION(ZVKNHA);
    CHECK_EXTENSION(ZVKNHB);
    CHECK_EXTENSION(ZVKSED);
    CHECK_EXTENSION(ZVKSH);
    CHECK_EXTENSION(ZVKT);
    CHECK_EXTENSION(ZFH);
    CHECK_EXTENSION(ZFHMIN);
    CHECK_EXTENSION(ZIHINTNTL);
    CHECK_EXTENSION(ZVFH);
    CHECK_EXTENSION(ZVFHMIN);
    CHECK_EXTENSION(ZFA);
    CHECK_EXTENSION(ZTSO);
    CHECK_EXTENSION(ZACAS);
    CHECK_EXTENSION(XANDESPMU);
    CHECK_EXTENSION(XLINUXENVCFG);
}

static void test_riscv_has_extension_likely(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    bool extension_likly = false;
    bool extension_unlikly = false;
    bool isa_extension = false;
    #define HAS_EXTENSION_CHECK(x) do { extension_likly = riscv_has_extension_likely(RISCV_ISA_EXT_##x); } while(0)
    #define ISA_EXTENSION_CHECK(x) do { isa_extension = riscv_isa_extension_available(NULL, x); } while(0)
    #define HAS_EXTENSION_CHECK_F(x) do { extension_unlikly = riscv_has_extension_unlikely(RISCV_ISA_EXT_##x); } while(0)
    #undef CHECK_EXTENSION
    #define CHECK_EXTENSION(x) do { HAS_EXTENSION_CHECK(x); ISA_EXTENSION_CHECK(x); HAS_EXTENSION_CHECK_F(x); if(extension_likly == isa_extension && extension_likly == extension_unlikly) { (*success)++; } else { (*err)++; pr_info("EXTENSION " #x " NOT ASSISTTENT\n");} } while(0)
    CHECK_EXTENSION(a);
    CHECK_EXTENSION(c);
    CHECK_EXTENSION(d);
    CHECK_EXTENSION(f);
    CHECK_EXTENSION(h);
    CHECK_EXTENSION(i);
    CHECK_EXTENSION(m);
    CHECK_EXTENSION(q);
    CHECK_EXTENSION(v);
    CHECK_EXTENSION(SSCOFPMF);
    CHECK_EXTENSION(SSTC);
    CHECK_EXTENSION(SVINVAL);
    CHECK_EXTENSION(SVPBMT);
    CHECK_EXTENSION(ZBB);
    CHECK_EXTENSION(ZICBOM);
    CHECK_EXTENSION(ZIHINTPAUSE);
    CHECK_EXTENSION(SVNAPOT);
    CHECK_EXTENSION(ZICBOZ);
    CHECK_EXTENSION(SMAIA);
    CHECK_EXTENSION(SSAIA);
    CHECK_EXTENSION(ZBA);
    CHECK_EXTENSION(ZBS);
    CHECK_EXTENSION(ZICNTR);
    CHECK_EXTENSION(ZICSR);
    CHECK_EXTENSION(ZIFENCEI);
    CHECK_EXTENSION(ZIHPM);
    CHECK_EXTENSION(SMSTATEEN);
    CHECK_EXTENSION(ZICOND);
    CHECK_EXTENSION(ZBC);
    CHECK_EXTENSION(ZBKB);
    CHECK_EXTENSION(ZBKC);
    CHECK_EXTENSION(ZBKX);
    CHECK_EXTENSION(ZKND);
    CHECK_EXTENSION(ZKNE);
    CHECK_EXTENSION(ZKNH);
    CHECK_EXTENSION(ZKR);
    CHECK_EXTENSION(ZKSED);
    CHECK_EXTENSION(ZKSH);
    CHECK_EXTENSION(ZKT);
    CHECK_EXTENSION(ZVBB);
    CHECK_EXTENSION(ZVBC);
    CHECK_EXTENSION(ZVKB);
    CHECK_EXTENSION(ZVKG);
    CHECK_EXTENSION(ZVKNED);
    CHECK_EXTENSION(ZVKNHA);
    CHECK_EXTENSION(ZVKNHB);
    CHECK_EXTENSION(ZVKSED);
    CHECK_EXTENSION(ZVKSH);
    CHECK_EXTENSION(ZVKT);
    CHECK_EXTENSION(ZFH);
    CHECK_EXTENSION(ZFHMIN);
    CHECK_EXTENSION(ZIHINTNTL);
    CHECK_EXTENSION(ZVFH);
    CHECK_EXTENSION(ZVFHMIN);
    CHECK_EXTENSION(ZFA);
    CHECK_EXTENSION(ZTSO);
    CHECK_EXTENSION(ZACAS);
    CHECK_EXTENSION(XANDESPMU);
    CHECK_EXTENSION(XLINUXENVCFG);
}

static void test_riscv_get_mvendor_id(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    unsigned int cpu = get_cpu();
    unsigned long sbi_mvendor_id = sbi_get_mvendorid();
    unsigned long cached_mvendor_id = riscv_cached_mvendorid(cpu);
    if(sbi_mvendor_id == cached_mvendor_id)
        (*success)++;
    else
    {
        (*err)++;
        pr_info("sbi_mvendor_id: %llx, cached_mvendor_id\n", sbi_mvendor_id, cached_mvendor_id);
        put_cpu();
        return;
    }
    put_cpu();
    pr_info("mvendorid: %llx\n", sbi_mvendor_id);
}

static void test_riscv_get_march_id(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    unsigned int cpu = get_cpu();
    unsigned long sbi_march_id = sbi_get_marchid();
    unsigned long cached_march_id = riscv_cached_marchid(cpu);
    if(sbi_march_id == cached_march_id)
        (*success)++;
    else 
    {
        (*err)++;
        pr_info("sbi_march_id: %llx, cached_march_id: %llx\n", sbi_march_id, cached_march_id);
        put_cpu();
        return;
    }
    put_cpu();
    pr_info("marchid: %llx\n", sbi_march_id);
}

static void test_sbi_get_mimpid(int* err, int* success)
{
    CHECK_TEST_FUNC_T_PARAMETER();
    unsigned int cpu = get_cpu();
    unsigned long sbi_mimp_id = sbi_get_mimpid();
    unsigned long cached_mimp_id = riscv_cached_mimpid(cpu);
    if(sbi_mimp_id != cached_mimp_id)
    {
        (*err)++;
        pr_info("sbi_mimp_id: %llx, cached_mimp_id: %llx\n", sbi_mimp_id, cached_mimp_id);
        put_cpu();
        return;
    }
    else
        (*success)++;
    put_cpu();
    pr_info("mimp_id: %llx\n", sbi_mimp_id);
}

static struct test_single_kit test_kits[] = {
    { "HWPROBE_API_KVALID", test_riscv_hwprobe_key_is_valid },
    { "HWPROBE_API_KBTMSK", test_hwprobe_key_is_bitmask     },
    { "HWPROBE_API_PIRCMP", test_riscv_hwprobe_pair_cmp     },
    { "HWCAP_API_ISABASET", test_riscv_isa_extension_base   },
    // { "HWCAP_API_GTELFCAP", test_riscv_get_elf_hwcap        },
    { "HWCAP_API_ISAENABL", test_riscv_isa_available        },
    { "HWCAP_API_EXTLIKLY", test_riscv_has_extension_likely },
    { "HWPROBE_MVENDIDTST", test_riscv_get_mvendor_id       },
    { "HWPROBE_MARCHIDTST", test_riscv_get_march_id         },
    { "HWPROBE_MIMLPIDTST", test_sbi_get_mimpid             },
};

static int __init test_hwprobe_module_init(void)
{
    int total_success = 0;
    int total_err = 0;
    int total_num = 0;
    int size = sizeof(test_kits) / sizeof(test_kits[0]);
    for(int i=0; i<size ;i++)
    {
        int tmp_success = 0;
        int tmp_err = 0;
        pr_info("=============TEST FOR %s =============\n", test_kits[i].name);
        test_kits[i].test_handler(&tmp_err, &tmp_success);
        pr_info("test success %d/%d\n", tmp_success, tmp_success + tmp_err);
        pr_info("test failed  %d/%d\n", tmp_err, tmp_success + tmp_err);
        total_success += tmp_success;
        total_err += tmp_err;
        total_num += (tmp_success + tmp_err);
        pr_info("=============TEST FOR %s END =========\n", test_kits[i].name);   
    }
    pr_info("=============TEST FOR ALL =============\n");
    pr_info("total test success %d/%d\n", total_success, total_num);
    pr_info("total test failed  %d/%d\n", total_err, total_num);
    pr_info("=============TEST FOR ALL END =========\n");
    return 0;
}

static void __exit test_hwprobe_module_exit(void)
{
    pr_info("exit!!!!!!!!!!!!!\n");
    return;
}

module_init(test_hwprobe_module_init);

module_exit(test_hwprobe_module_exit);

MODULE_LICENSE("GPL");

测试结果

[   89.336992] =============TEST FOR HWPROBE_API_KVALID =============
[   89.339827] test success 7008/7008
[   89.339869] test failed  0/7008
[   89.339895] =============TEST FOR HWPROBE_API_KVALID END =========
[   89.339918] =============TEST FOR HWPROBE_API_KBTMSK =============
[   89.339988] test success 5001/5001
[   89.340000] test failed  0/5001
[   89.340010] =============TEST FOR HWPROBE_API_KBTMSK END =========
[   89.340020] =============TEST FOR HWPROBE_API_PIRCMP =============
[   89.343923] test success 15033/15033
[   89.343942] test failed  0/15033
[   89.343953] =============TEST FOR HWPROBE_API_PIRCMP END =========
[   89.343963] =============TEST FOR HWCAP_API_ISABASET =============
[   89.344018] support RISCV_ISA_a
[   89.344040] support RISCV_ISA_c
[   89.344061] support RISCV_ISA_d
[   89.344082] support RISCV_ISA_f
[   89.344102] support RISCV_ISA_h
[   89.344123] support RISCV_ISA_i
[   89.344145] support RISCV_ISA_m
[   89.344167] base extension RISCV_ISA_q not support!
[   89.344186] base extension RISCV_ISA_v not support!
[   89.344206] test success 7/9
[   89.344217] test failed  2/9
[   89.344227] =============TEST FOR HWCAP_API_ISABASET END =========
[   89.344237] =============TEST FOR HWCAP_API_ISAENABL =============
[   89.344273] extension RISCV_ISA_a support
[   89.344307] extension RISCV_ISA_c support
[   89.344332] extension RISCV_ISA_d support
[   89.344355] extension RISCV_ISA_f support
[   89.344379] extension RISCV_ISA_h support
[   89.344403] extension RISCV_ISA_i support
[   89.344426] extension RISCV_ISA_m support
[   89.344450] extension RISCV_ISA_q not support
[   89.344472] extension RISCV_ISA_v not support
[   89.344493] extension RISCV_ISA_SSCOFPMF not support
[   89.344514] extension RISCV_ISA_SSTC support
[   89.344537] extension RISCV_ISA_SVINVAL not support
[   89.344558] extension RISCV_ISA_SVPBMT not support
[   89.344581] extension RISCV_ISA_ZBB support
[   89.344613] extension RISCV_ISA_ZICBOM support
[   89.344717] extension RISCV_ISA_ZIHINTPAUSE support
[   89.344743] extension RISCV_ISA_SVNAPOT not support
[   89.344764] extension RISCV_ISA_ZICBOZ support
[   89.344796] extension RISCV_ISA_SMAIA not support
[   89.344817] extension RISCV_ISA_SSAIA not support
[   89.344839] extension RISCV_ISA_ZBA support
[   89.344862] extension RISCV_ISA_ZBS support
[   89.344886] extension RISCV_ISA_ZICNTR support
[   89.344909] extension RISCV_ISA_ZICSR support
[   89.344933] extension RISCV_ISA_ZIFENCEI support
[   89.344956] extension RISCV_ISA_ZIHPM support
[   89.344979] extension RISCV_ISA_SMSTATEEN not support
[   89.345000] extension RISCV_ISA_ZICOND not support
[   89.345021] extension RISCV_ISA_ZBC support
[   89.345045] extension RISCV_ISA_ZBKB not support
[   89.345065] extension RISCV_ISA_ZBKC not support
[   89.345086] extension RISCV_ISA_ZBKX not support
[   89.345106] extension RISCV_ISA_ZKND not support
[   89.345127] extension RISCV_ISA_ZKNE not support
[   89.345148] extension RISCV_ISA_ZKNH not support
[   89.345168] extension RISCV_ISA_ZKR not support
[   89.345189] extension RISCV_ISA_ZKSED not support
[   89.345209] extension RISCV_ISA_ZKSH not support
[   89.345231] extension RISCV_ISA_ZKT not support
[   89.345252] extension RISCV_ISA_ZVBB not support
[   89.345272] extension RISCV_ISA_ZVBC not support
[   89.345293] extension RISCV_ISA_ZVKB not support
[   89.345314] extension RISCV_ISA_ZVKG not support
[   89.345334] extension RISCV_ISA_ZVKNED not support
[   89.345362] extension RISCV_ISA_ZVKNHA not support
[   89.345383] extension RISCV_ISA_ZVKNHB not support
[   89.345403] extension RISCV_ISA_ZVKSED not support
[   89.345424] extension RISCV_ISA_ZVKSH not support
[   89.345445] extension RISCV_ISA_ZVKT not support
[   89.345465] extension RISCV_ISA_ZFH not support
[   89.345486] extension RISCV_ISA_ZFHMIN not support
[   89.345507] extension RISCV_ISA_ZIHINTNTL not support
[   89.345528] extension RISCV_ISA_ZVFH not support
[   89.345549] extension RISCV_ISA_ZVFHMIN not support
[   89.345570] extension RISCV_ISA_ZFA support
[   89.345593] extension RISCV_ISA_ZTSO not support
[   89.345614] extension RISCV_ISA_ZACAS not support
[   89.345634] extension RISCV_ISA_XANDESPMU not support
[   89.345655] extension RISCV_ISA_XLINUXENVCFG support
[   89.345681] test success 59/59
[   89.345692] test failed  0/59
[   89.345703] =============TEST FOR HWCAP_API_ISAENABL END =========
[   89.345712] =============TEST FOR HWCAP_API_EXTLIKLY =============
[   89.347091] test success 59/59
[   89.347111] test failed  0/59
[   89.347123] =============TEST FOR HWCAP_API_EXTLIKLY END =========
[   89.347133] =============TEST FOR HWPROBE_MVENDIDTST =============
[   89.347190] mvendorid: 0
[   89.347211] test success 1/1
[   89.347222] test failed  0/1
[   89.347231] =============TEST FOR HWPROBE_MVENDIDTST END =========
[   89.347241] =============TEST FOR HWPROBE_MARCHIDTST =============
[   89.347288] marchid: 0
[   89.347307] test success 1/1
[   89.347317] test failed  0/1
[   89.347327] =============TEST FOR HWPROBE_MARCHIDTST END =========
[   89.347337] =============TEST FOR HWPROBE_MIMLPIDTST =============
[   89.347383] mimp_id: 0
[   89.347401] test success 1/1
[   89.347412] test failed  0/1
[   89.347421] =============TEST FOR HWPROBE_MIMLPIDTST END =========
[   89.347435] =============TEST FOR ALL =============
[   89.347448] total test success 27170/27172
[   89.347463] total test failed  2/27172
[   89.347478] =============TEST FOR ALL END =========

额外说明

这里有两个 failed 是因为源码里面 对于 base extension v 和 p 不支持的话,就默认成错误来处理

用户态测试代码

主要是测试了用户态在 BACKPORT 后的 syscall 的功能

#include <asm/hwprobe.h>
#include <asm/unistd.h>
#include <unistd.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

long sys_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
                       size_t cpusetsize, cpu_set_t *cpus,
                       unsigned int flags)
{
        long ret = syscall(__NR_riscv_hwprobe, pairs, pair_count, cpusetsize, cpus, flags);
        return ret;
}

static struct riscv_hwprobe ask_hwprobe[] = {
        {.key = RISCV_HWPROBE_KEY_MVENDORID, .value = 233},
        {.key = RISCV_HWPROBE_KEY_MARCHID, .value = 233},
        {.key = RISCV_HWPROBE_KEY_MIMPID, .value = 233},
        {.key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value =233},
        {.key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = 233},
        {.key = RISCV_HWPROBE_KEY_CPUPERF_0, .value = 233},
#ifdef BACKPORT
        {.key = RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE, .value = 233},
#endif
};

int main(int argc, char* argv[])
{
        int size = sizeof(ask_hwprobe) / sizeof(ask_hwprobe[0]);
        int ret = sys_riscv_hwprobe(ask_hwprobe, size, 0, NULL, 0);
        if(ret != 0)
        {
                printf("hwprobe syscall error!\n");
                return -1;
        }
        printf("mvendor id: %llx\n", ask_hwprobe[0].value);
        printf("march id: %llx\n", ask_hwprobe[1].value);
        printf("mimp id: %llx\n", ask_hwprobe[2].value);
        printf("ARCH BASE BEHAVIOR: \n");
        if(RISCV_HWPROBE_BASE_BEHAVIOR_IMA & ask_hwprobe[3].value)
        {
                printf("RISCV_HWPROBE_BASE_BEHAVIOR_IMA\n");
        }
        else
        {
                printf("ERROR BEHAVIOR\n");
        }

#define CHECK(type,what) do {      \
                                if(ask_hwprobe[4].value & RISCV_HWPROBE_##type##_##what) \
                                {\
                                        printf("RISC-V " #type " Extension " #what " Support!\n");\
                                }\
                                else \
                                {\
                                        printf("RISC-V " #type " Extension " #what " Not Support!\n");\
                                }\
                        } while(0)

#define BASE_CHECK(x)   CHECK(IMA,x)
#define EXTENSION_CHECK(x)      CHECK(EXT,x)
        BASE_CHECK(FD);
        BASE_CHECK(C);
        BASE_CHECK(V);

        EXTENSION_CHECK(ZBA);
        EXTENSION_CHECK(ZBB);
        EXTENSION_CHECK(ZBS);
#ifdef BACKPORT
        EXTENSION_CHECK(ZICBOZ);
        EXTENSION_CHECK(ZBC);
        EXTENSION_CHECK(ZBKB);
        EXTENSION_CHECK(ZBKC);
        EXTENSION_CHECK(ZBKX);
        EXTENSION_CHECK(ZKND);
        EXTENSION_CHECK(ZKNE);
        EXTENSION_CHECK(ZKNH);
        EXTENSION_CHECK(ZKSED);
        EXTENSION_CHECK(ZKSH);
        EXTENSION_CHECK(ZKT);
        EXTENSION_CHECK(ZVBB);
        EXTENSION_CHECK(ZVBC);
        EXTENSION_CHECK(ZVKB);
        EXTENSION_CHECK(ZVKG);
        EXTENSION_CHECK(ZVKNED);
        EXTENSION_CHECK(ZVKNHA);
        EXTENSION_CHECK(ZVKNHB);
        EXTENSION_CHECK(ZVKSED);
        EXTENSION_CHECK(ZVKSH);
        EXTENSION_CHECK(ZVKT);
        EXTENSION_CHECK(ZFH);
        EXTENSION_CHECK(ZFHMIN);
        EXTENSION_CHECK(ZIHINTNTL);
        EXTENSION_CHECK(ZVFH);
        EXTENSION_CHECK(ZVFHMIN);
        EXTENSION_CHECK(ZFA);
        EXTENSION_CHECK(ZTSO);
        EXTENSION_CHECK(ZACAS);
        EXTENSION_CHECK(ZICOND);
        EXTENSION_CHECK(ZIHINTPAUSE);
#endif

#define PERFORMANCE_CHECK(x) do {       \
                                  if(ask_hwprobe[5].value & RISCV_HWPROBE_MISALIGNED_##x) \
                                  { \
                                        printf("MISALIGNED ACCESS MEMORY PERFORMANCE: " #x " \n");\
                                  }\
                                } while(0)
        PERFORMANCE_CHECK(UNKNOWN);
        PERFORMANCE_CHECK(EMULATED);
        PERFORMANCE_CHECK(SLOW);
        PERFORMANCE_CHECK(FAST);
        PERFORMANCE_CHECK(UNSUPPORTED);

#ifdef BACKPORT
        PERFORMANCE_CHECK(MASK);
#endif

#ifdef BACKPORT
        printf("ZICBOZ_BLOCK_SIZE : %llx\n", ask_hwprobe[6].value);
#endif

        return 0;
}

测试结果

mvendor id: 0
march id: 0
mimp id: 0
ARCH BASE BEHAVIOR: 
RISCV_HWPROBE_BASE_BEHAVIOR_IMA
RISC-V IMA Extension FD Support!
RISC-V IMA Extension C Support!
RISC-V IMA Extension V Not Support!
RISC-V EXT Extension ZBA Support!
RISC-V EXT Extension ZBB Support!
RISC-V EXT Extension ZBS Support!
RISC-V EXT Extension ZICBOZ Support!
RISC-V EXT Extension ZBC Support!
RISC-V EXT Extension ZBKB Not Support!
RISC-V EXT Extension ZBKC Not Support!
RISC-V EXT Extension ZBKX Not Support!
RISC-V EXT Extension ZKND Not Support!
RISC-V EXT Extension ZKNE Not Support!
RISC-V EXT Extension ZKNH Not Support!
RISC-V EXT Extension ZKSED Not Support!
RISC-V EXT Extension ZKSH Not Support!
RISC-V EXT Extension ZKT Not Support!
RISC-V EXT Extension ZVBB Not Support!
RISC-V EXT Extension ZVBC Not Support!
RISC-V EXT Extension ZVKB Not Support!
RISC-V EXT Extension ZVKG Not Support!
RISC-V EXT Extension ZVKNED Not Support!
RISC-V EXT Extension ZVKNHA Not Support!
RISC-V EXT Extension ZVKNHB Not Support!
RISC-V EXT Extension ZVKSED Not Support!
RISC-V EXT Extension ZVKSH Not Support!
RISC-V EXT Extension ZVKT Not Support!
RISC-V EXT Extension ZFH Not Support!
RISC-V EXT Extension ZFHMIN Not Support!
RISC-V EXT Extension ZIHINTNTL Not Support!
RISC-V EXT Extension ZVFH Not Support!
RISC-V EXT Extension ZVFHMIN Not Support!
RISC-V EXT Extension ZFA Support!
RISC-V EXT Extension ZTSO Not Support!
RISC-V EXT Extension ZACAS Not Support!
RISC-V EXT Extension ZICOND Not Support!
RISC-V EXT Extension ZIHINTPAUSE Support!
MISALIGNED ACCESS MEMORY PERFORMANCE: EMULATED 
MISALIGNED ACCESS MEMORY PERFORMANCE: SLOW 
MISALIGNED ACCESS MEMORY PERFORMANCE: FAST 
MISALIGNED ACCESS MEMORY PERFORMANCE: MASK 
ZICBOZ_BLOCK_SIZE : 40

结果

测试缺陷

Jer6y commented 3 months ago

0001-hwprobe-syscall-backport.patch.tar.gz