fwctl cxl 驱动程序

作者:

Dave Jiang

概述

CXL 规范定义了一组可以发送到 CXL 设备或交换机的邮箱的命令。它还为发送到邮箱的供应商特定命令留出了空间。 fwctl 提供了一条路径,用于从用户空间向设备发出由内核驱动程序调节的一组允许的邮箱命令。

以下 3 个命令将用于支持 CXL 特性: CXL 规范 r3.1 8.2.9.6.1 获取支持的特性(操作码 0500h) CXL 规范 r3.1 8.2.9.6.2 获取特性(操作码 0501h) CXL 规范 r3.1 8.2.9.6.3 设置特性(操作码 0502h)

“获取支持的特性”返回的数据可能会被内核驱动程序过滤,以删除内核禁止的或内核独占使用的任何特性。驱动程序会将“获取支持的特性支持的特性条目”的“设置特性大小”设置为 0,以表明该特性无法修改。“获取支持的特性”命令和“获取特性”属于 FWCTL_RPC_CONFIGURATION 的 fwctl 策略。

对于“设置特性”命令,访问策略目前分为两类,具体取决于设备报告的“设置特性”效果。如果“设置特性”将导致设备立即更改,则 fwctl 访问策略必须为 FWCTL_RPC_DEBUG_WRITE_FULL。此级别的效果是用于设置效果掩码的“立即配置更改”、“立即数据更改”、“立即策略更改”或“立即日志更改”。如果效果是“带有冷重置的配置更改”或“带有传统重置的配置更改”,则 fwctl 访问策略必须为 FWCTL_RPC_DEBUG_WRITE 或更高。

fwctl cxl 用户 API

struct fwctl_rpc_cxl

用于 CXL 的 ioctl(FWCTL_RPC) 输入

定义:

struct fwctl_rpc_cxl {
    __u32 opcode;
    __u32 flags;
    __u32 op_size;
    __u32 reserved1;
    union {
        struct cxl_mbox_get_sup_feats_in get_sup_feats_in;
        struct cxl_mbox_get_feat_in get_feat_in;
        struct cxl_mbox_set_feat_in set_feat_in;
    };
};

成员

opcode

CXL 邮箱命令操作码

flags

命令的标志(输入)。

op_size

输入负载的大小。

reserved1

已保留。必须为 0。

{unnamed_union}

anonymous

get_sup_feats_in

获取支持的特性输入

get_feat_in

获取特性输入

set_feat_in

设置特性输入

struct fwctl_rpc_cxl_out

用于 CXL 的 ioctl(FWCTL_RPC) 输出

定义:

struct fwctl_rpc_cxl_out {
    __u32 size;
    __u32 retval;
    union {
        struct cxl_mbox_get_sup_feats_out get_sup_feats_out;
        __u8 payload[];
    };
};

成员

size

输出负载的大小

retval

来自设备的返回值

{unnamed_union}

anonymous

get_sup_feats_out

获取支持的特性输出

payload

负载的原始字节流

1. 驱动程序信息查询

应用程序的第一步是发出 ioctl(FWCTL_CMD_INFO)。ioctl 的成功调用意味着“特性”功能正在运行,并返回一个全零的 32 位负载。需要使用设置为 FWCTL_DEVICE_TYPE_CXLfwctl_info.out_device_type 填充 struct fwctl_info。返回的数据应为包含保留的 32 位字段(应全部为零)的 struct fwctl_info_cxl

2. 发送硬件命令

下一步是通过 ioctl(FWCTL_RPC) 从用户空间向驱动程序发送“获取支持的特性”命令。 struct fwctl_rpc_cxlfwctl_rpc.in 指向。 struct fwctl_rpc_cxl.in_payload 指向 CXL 规范定义的硬件输入结构。 fwctl_rpc.out 指向包含一个内联作为 fwctl_rpc_cxl_out.payload 的硬件输出数据的 struct fwctl_rpc_cxl_out 的缓冲区。此命令被调用两次。第一次是为了检索支持的特性数量。第二次是为了检索作为输出数据的特定特性详细信息。

获取特定特性详细信息后,可以适当编程并发送“获取/设置特性”命令。对于“设置特性”命令,检索到的特性信息包含一个效果字段,该字段详细说明了将触发的“设置特性”命令的结果。这将告知用户系统是否已配置为允许“设置特性”命令。

“获取特性”的代码示例

static int cxl_fwctl_rpc_get_test_feature(int fd, struct test_feature *feat_ctx,
                                          const uint32_t expected_data)
{
        struct cxl_mbox_get_feat_in *feat_in;
        struct fwctl_rpc_cxl_out *out;
        struct fwctl_rpc rpc = {0};
        struct fwctl_rpc_cxl *in;
        size_t out_size, in_size;
        uint32_t val;
        void *data;
        int rc;

        in_size = sizeof(*in) + sizeof(*feat_in);
        rc = posix_memalign((void **)&in, 16, in_size);
        if (rc)
                return -ENOMEM;
        memset(in, 0, in_size);
        feat_in = &in->get_feat_in;

        uuid_copy(feat_in->uuid, feat_ctx->uuid);
        feat_in->count = feat_ctx->get_size;

        out_size = sizeof(*out) + feat_ctx->get_size;
        rc = posix_memalign((void **)&out, 16, out_size);
        if (rc)
                goto free_in;
        memset(out, 0, out_size);

        in->opcode = CXL_MBOX_OPCODE_GET_FEATURE;
        in->op_size = sizeof(*feat_in);

        rpc.size = sizeof(rpc);
        rpc.scope = FWCTL_RPC_CONFIGURATION;
        rpc.in_len = in_size;
        rpc.out_len = out_size;
        rpc.in = (uint64_t)(uint64_t *)in;
        rpc.out = (uint64_t)(uint64_t *)out;

        rc = send_command(fd, &rpc, out);
        if (rc)
                goto free_all;

        data = out->payload;
        val = le32toh(*(__le32 *)data);
        if (memcmp(&val, &expected_data, sizeof(val)) != 0) {
                rc = -ENXIO;
                goto free_all;
        }

free_all:
        free(out);
free_in:
        free(in);
        return rc;
}

查看 CXL CLI 测试目录 <https://github.com/pmem/ndctl/tree/main/test/fwctl.c> 以获取有关如何执行此路径的详细用户代码示例。

fwctl cxl 内核 API

int devm_cxl_setup_features(struct cxl_dev_state *cxlds)

分配和初始化特性上下文

参数

struct cxl_dev_state *cxlds

CXL 设备上下文

描述

成功时返回 0,失败时返回 -errno。

struct cxl_features_state

设备的特性状态

定义:

struct cxl_features_state {
    struct cxl_dev_state *cxlds;
    struct cxl_feat_entries {
        int num_features;
        int num_user_features;
        struct cxl_feat_entry ent[] ;
    } *entries;
};

成员

cxlds

指向 CXL 设备状态的指针

entries

CXl 特性条目上下文