This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/66AK2H12:CMEM/CMEMK API 在处理器 SDK 03.03.00.04中损坏

Guru**** 2563770 points
Other Parts Discussed in Thread: 66AK2H12

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/613020/linux-66ak2h12-cmem-cmemk-api-is-broken-in-processor-sdk-03-03-00-04

器件型号:66AK2H12

工具/软件:Linux

问题表现为此错误

TI-mctd:/home/gtbldadm/processor-sdk-linux-krogoth-build/build-CORTEX_1/arago-tmp-external-linaro-toolchain/work/k2hk_evm-linux-gnueabi/opencl/1.1.12.0-r0.0/git/host/mct-demon/cmem_allocator.h:80:CmemAllocator::CmemAllocator ():断言`ddr_alloc_dsp_addr_= DDR_addr'失败。 

启动 ti-MCT-daemon 时。  我进行了大量挖掘、并在 ludev/include/ti/cmem.h 中找到

UNION CMEM_Allocunion{
[... 等等...]
struct{/**<*/
unsigned long physp;
unsigned long long size;
} get_block_outparams;/**<*/
[... 等等...]
};

和 ludev src/cmem/module/cmemk.c 中

案例 CMEM_IOCGETBLOCK:
_D (收到"GETBLOCK ioctl。\n");

if (copy_ffrom _user (&allocDesc、argp、sizeof (allocDesc))){
返回-efault;
}

BI = allocDesc.blockid;
if (bi >= nblocks || bi < 0){
__E ("GETBLOCK:无效的块 ID %d\n"、bi);

return -EINVAL;
}

allocDesc.get_block_outparams.physp = block_start[bi];
allocDesc.get_block_outparams.size = block_end[bi]-
block_start[bi];

_D ("GETBLOCK:正在返回 PHY 基体"
"%#llx、size %#llx。\n"、allocDesc.get_block_outparams.physp、
allocDesc.get_block_outparams.size);

if (copy_to _user (argp、&allocDesc、sizeof (allocDesc))){
返回-efault;
}

中断;

因此、至少就 cmemk 器件驱动程序中的 ioctl 而言、返回的物理地址和大小都是"unsigned long long"、即64位值。

同时、在 ludev/src/cmem/api/cmem.c 中、我们看到物理地址的类型为"off_t":

静态 int getBlock (int blockid、off_t * pphys_base、unsigned long * psize)
{
UNION CMEM_Allocunion 块;
Int RV;

_D ("getBlock:entered\n");

if (!validate_init()){
return -1;
}

block.blockid = blockid;
RV = ioctl (cmem_fd、CMEM_IOCGETBLOCK | CMEM_IOCMAGIC、&block);
如果(RV!= 0){
_E ("getBlock:Failed to retrieve memory block bounds for block %d "(getBlock:无法检索块%d 的内存块边界)
"从驱动程序:%d.\n"、blockid、rv);

返回-1;
}

*pphys_base =(off_t) block.get_block_outparams.physp;
*psize = block.get_block_outparams.size;

_D ("getBlock:正在退出,ioctl CMEM_IOCGETBLOCK 成功,"
"返回*pphys_base=%#llx、*psize=%#llx\n"、
(unsigned long long)(*pphys_base)、*psize);

返回0;
}

int CMEM_getBlock (off_t *pphys_base、unsigned long * psize)
{
返回 getBlock (0、pphys_base、psize);
}

遗憾的是、"off_t"是一种32位类型:

$ cat off_t.c
#include 

int main (int argc、char * argv[])
{
printf ("sizeof (off_t)=%d 位\n"、sizeof (off_t)*8);
返回0;
}

root@k2hk EVM:~#./off_t
sizeof (off_t)= 32位

K2H 上的物理地址实际上是36位值、DDR 从0x800000000开始、因此如果 CMEM 块在 DDR 中、API 会失败。  据我所知、这一点在 Processor SDK 的 v4中也没有得到修复。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    我将查看此内容并更新该主题。

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    了解一下 cat /proc/iomem 报告的内容:
    8000000000-9ffffffff:系统 RAM (引导别名)
    c0000000-ffffff:系统 RAM (引导别名)
    800000000000000-81ffffffff:系统 RAM
    800008000-8008bb043:内核代码
    800904000-80098f0c3:内核数据
    822000000-828ffff:CMEM
    829000000-83fffffff: CMEM
    840000000-87ffffffff:系统 RAM
    root@k2hk EVM:~#

    这符合 k2hk) EVM-cmem.dtsi 中的定义:
    /{
    保留存储器{

    cmem_block_mem_0:cmem_block_mem@829000000{
    REG =<0x00000008 0x29000000 0x00000000 0x17000000>;
    无地图;
    状态="正常";
    };

    cmem_block_mem_1:cmem_block_mem@00c100000{
    REG =<0x00000000 0x0c100000 0x00000000 0x00480000>;
    无地图;
    状态="正常";
    };

    cmem_block_mem_2:cmem_block_mem@822000000{
    REG =<0x00000008 0x22000000 0x00000000 0x07000000>;
    无地图;
    状态="正常";
    };
    };

    cmem{
    兼容="ti、cmem";
    #address-cells =<1>;
    #size-cells =<0>;

    #pool-size-cells =<2>;

    状态="正常";

    cmem_block_0:cmem_block@0{
    reg =<0>;
    memory-region =<&cmem_block_mem_0>;
    cmem-buf-Pools =<1 0x00000000 0x17000000>;
    };

    cmem_block_1:cmem_block@1{
    reg =<1>;
    memory-region =<&cmem_block_mem_1>;
    };

    cmem_block_2:cmem_block@2{
    reg =<2>;
    memory-region =<&cmem_block_mem_2>;
    };
    };

    };

    &DSP_common_mpm_area{
    REG =<0x00000008 0x20000000 0x00000000 0x02000000>;
    };
    mpm_mem{(&M)
    reg =<0xa0000000 0x02000000>;
    };

    您可以看到、CMEM 块实际上是系统 RAM 中的保留存储器区域。 以上内容来自 ti-processor-sdk-linux-k2hk EVM-03.02.00.05。 在最新的 SDK4中、情况相似。

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我想你没有达到我的观点。 API 被中断、因为试图通过将大量"无符号长整型"更改为"off_t"来增加对大于32位的物理地址的支持、但不幸的是、这相当于此平台上的不运行、因为"off_t"是"无符号长整型"的 typedef。 看看

    git.ti.com/.../1322ebc0fe186eb5fe78d060c3f6afbb44ea3332

    引用提交日志

    通过执行上述项目符号、一切都将在何时正确调整
    phys_addr_t (内核级)和 off_t (用户级)为32位
    或64位类型。

    但是、正如我说过的、它在这个平台上不起作用、因为内核中的 phys_addr_t 是64位、而用户空间中的 off_t 是32位。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我使用"CFLAGS=-D_DEBUG"重新编译了 API 库、以获取所有调试详细信息、然后编写了一个非常简单的程序来展示该错误。  这是程序

    #include 
    #include 
    #include 
    #include 
    
    #define CMEM_ERROR (x) do{if ((x)< 0){fprintf (stderr、#x " failed\n");exit (exit_failure);}while (0)
    
    int main (int argc、char * argv[])
    {
    int i、nblocks;
    
    CMEM_ERROR (CMEM_INIT ());
    CMEM_ERROR (CMEM_getNumBlocks (_nblocks));
    对于(i = 0;i < nblocks;++i){
    CMEM_BlockAttrs atts ={0};
    CMEM_ERROR (CMEM_getBlockAttrs (i、&attrs));
    printf ("CMEM 内存块%d:PHY 开始=%#llx、大小=%#llx\n"、
    i、(unsigned long long) attrs.phys_base、attrs.size);
    }
    
    CMEM_ERROR (CMEM_EXIT());
    返回0;
    }
    

    这是我在运行程序时获得的输出

    CMEM 调试:INIT:输入- ref_count 0、cmem_fd -2
    CMEM 调试:INIT:成功打开/dev/cmem、匹配驱动程序版本...
    CMEM 调试:getversion:输入
    的 CMEM 调试:getversion:正在退出,ioctl CMEM_IOCGETVERSION 返回0x4130001
    CMEM 调试:初始化:... 匹配良好(0x4130001)
    CMEM 调试:初始化:退出、返回成功
    CMEM 调试:getNumBlocks:进入
    CMEM 调试:getNumBlocks:退出、ioctl CMEM_IOCGENUMBLOCK 成功、返回* pnblocks=2
    CMEM 调试:getBlock:
    getBlock:exiting、ioctl CMEM suc1 = 0x000000、getCMEM size
    = 0x30000000_bock = 0xpCMEM
    大小:getCMEM 输入
    的 CMEM 调试:getBlock:退出、ioctl CMEM_IOCGETBLOCK 成功、返回* pphys_base=0xc100000、* psize=0x480000
    CMEM 存储器块1:phys start = 0xc100000、size = 0x480000
    CMEM
    递减调试:exit:ref_count 1、cmmem_fd
    :exit /dev/cmem
    CMEM 调试:exit CMEM:exit CMEM (退出 CMEM) 0:exit CMEM 参考计数:exit CMEM:exit CMEM 退出、返回0
    

    我想特别提请大家注意输出中的这两条线

    CMEM 调试:getBlock:退出、ioctl CMEM_IOCGETBLOCK 成功、返回* pphys_base=0x830000000、* psize=0x18000000
    CMEM 存储器块0:PHY 开始= 0x30000000、大小= 0x18000000
    

    其中显示了我所讨论的内容:物理地址的最高有效位在 API 中丢失。  这在函数 ludev src/cmem/api/cmem.c:971中发生

    静态 int getBlock (int blockid、off_t * pphys_base、unsigned long * psize)
    {
    UNION CMEM_Allocunion 块;
    Int RV;
    
    _D ("getBlock:entered\n");
    
    if (!validate_init()){
    return -1;
    }
    
    block.blockid = blockid;
    RV = ioctl (cmem_fd、CMEM_IOCGETBLOCK | CMEM_IOCMAGIC、&block);
    如果(RV!= 0){
    _E ("getBlock:Failed to retrieve memory block bounds for block %d "(getBlock:无法检索块%d 的内存块边界)
    "从驱动程序:%d.\n"、blockid、rv);
    
    返回-1;
    }
    
    *pphys_base =(off_t) block.get_block_outparams.physp;
    *psize = block.get_block_outparams.size;
    
    _D ("getBlock:正在退出,ioctl CMEM_IOCGETBLOCK 成功,"
    "返回*pphys_base=%#llx、*psize=%#llx\n"、
    (unsigned long long)(*pphys_base)、*psize);
    
    返回0;
    }
    

    它使用 ioctl 调用 cmemk 内核驱动 程序、并将其传递为 CMEM_Allocunion。  正如我说过的 upthread、该联合体将物理地址视为"无符号超长整型"(64位)

    UNION CMEM_Allocunion{
    //为清晰起见省略了其他 UNION 成员*/
    struct{/**<*/
    unsigned long physp;
    unsigned long long size;
    } ALLOG_POOL_outparams;/**<*/
    /*为清晰起见省略了其他联合体成员*/
    };
    

    但是、getBlock 函数在返回前将其转换为"off_t"、并截断最高有效32位(其中4位实际上在66AK2H12上使用)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、

    我们使用"-D_file_offset_bits=64"标志编译/构建 OpenCL 运行时、使"off_t"类型为64位。 在 K2H EVM 上安装 PSDK 3.3或更高版本、加载 ti-mctd 并运行 OpenCL 示例时没有问题。

    您是否正在尝试构建自己的 OpenCL 或 PSDK? 您能否尝试下载库存 PSDK 3.3并查看您是否发现了相同的问题、然后从那里继续?

    谢谢!

    -元