【分享】MPSoC Linux CCI Cache 同步设计

作者:付汉杰,hankf@xilinx.com

1. 参考文档 1.1. AR69446

AR# 69446 Zynq UltraScale+ MPSoC Example Design - Use AXI HPC port to perform coherent transfers

1.2. Zynq UltraScale MPSoC Cache Coherency

Zynq UltraScale MPSoC Cache Coherency

1.3. MPSoC HPC 连接

2. 主要更改 2.1. AxCACHE

需要把AXI上的AxCACHE,也就是ARCACHE[3:0]和AWCACHE[3:0],设置成1111, 表示Write-back Read and Write-allocate。

2.2. AxPROT[1] 2.3. Cache监听(Snooping)

缺省情况下,MPSoC CCI (Cache Coherent Interconnect)不监听APU cluster。为了利用CCI cache同步功能,需要设置寄存器Snoop_Control_Register_S3的最低位,使CCI监听APU cluster。
寄存器Snoop_Control_Register_S3的地址在0xFD6E4000,最低位的含义使Enable issuing of snoop requests from slave interface S3。

2.3.1. 修改FSBL

可以在FSBL里修改Snoop_Control_Register_S3。

case XFSBL_STAGE4:
{

XFsbl_Printf(DEBUG_INFO,
"================= In Stage 4 ============ \n\r");

{
/* Modify Register Snoop_Control_Register_S3 for HPC Cache Cohenercy */
unsigned int ui_snoop_control=0;
XFsbl_Printf(DEBUG_PRINT_ALWAYS,"Check snoop control register at 0xfd6e4000.\n\r");
ui_snoop_control = XFsbl_In32(0xfd6e4000);
XFsbl_Printf(DEBUG_PRINT_ALWAYS,"Snoop control register at 0xfd6e4000 original value: 0x%08x.\n\r", ui_snoop_control );
XFsbl_Out32(0xfd6e4000, ui_snoop_control|0x1);

ui_snoop_control = XFsbl_In32(0xfd6e4000);
XFsbl_Printf(DEBUG_PRINT_ALWAYS,"Snoop control register at 0xfd6e4000 new value: 0x%08x.\n\r", ui_snoop_control );
}

/**
* Handoff to the applications
* Handoff address
* xip
* ps7 post config
*/
FsblStatus = XFsbl_Handoff(&FsblInstance, PartitionNum, EarlyHandoff);

... ...
}

2.4. Broadcasting Shareable

为了使相关传输被CCI监听,需要设置寄存器lpd_apu的最低两位为1,而且必须在A53处于复位态时设置。我们利用MPSoC BootROM在加载时设置寄存器lpd_apu。
为了用MPSoC BootROM在加载时设置寄存器lpd_apu,需要准备寄存器初始化文件,并且使用寄存器初始化文件创建启动文件boot.bin。

2.4.1. 寄存器初始化文件

.set. 0xFF41A040 = 0x3;

2.4.2. 修改启动文件boot.bin的配置信息

在启动文件boot.bin的配置信息中,以关键字"[init]"添加寄存器初始化文件。

//arch = zynqmp; split = false; format = BIN
the_ROM_image:
{
...
[init]
\regs.init
}

完整的boot.bin的配置信息,bootgen.bif

/* bootgen -arch zynqmp -image bootgen.bif -o BOOT.BIN -w on */

the_ROM_image:
{
[bootloader, destination_cpu=a53-0] ./zcu106_fsbl.elf
[pmufw_image] ./images/linux/pmufw.elf
[destination_device=pl] ./images/linux/system.bit
[destination_cpu=a53-0, exception_level=el-3, trustzone] ./images/linux/bl31.elf
[destination_cpu=a53-0, exception_level=el-2] ./images/linux/u-boot.elf
[init]./regs.init
}

2.4.3. 创建启动文件boot.bin

创建启动文件boot.bin

$ bootgen -arch zynqmp -image bootgen.bif -o BOOT.BIN -w on

****** Xilinx Bootgen v2019.1
**** Build date : May 24 2019-14:54:05
** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.

3. 测试环境 3.1. 测试工具

测试过程,使用Vivado 2019.1创建逻辑设计和编译逻辑工程;使用PetaLinux 2019.1 创建和编译Linux工程。

3.2. 测试工程

为了简化设计,使用ZCU106 BSP 2019.1 作为基础。

3.2.1. 逻辑设计

对于逻辑设计,删除了ZCU106 BSP 2019.1中的其它逻辑设计,然后添加了相关设计。

3.2.2. Linux工程

对于Linux工程,以ZCU106 BSP 2019.1创建PetaLinux工程,再倒入新的逻辑设计HDF文件。

4. 硬件测试工程

可以添加CDMA和AXI DMA,连接到HPC端口,测试CCI cache同步功能。

4.1. DMA硬件设计 4.1.1. MPSoC顶层设计

MPSoC顶层设计

测试中,使用了HPC0端口,使用了GPIO去驱动AxCACHE,AxPROT[1]信号。

4.1.2. DMA内部设计

4.1.3. MPSoC地址分配

5. 测试软件 5.1. DMA驱动

在Linux Kernel中使能如下选项,加入DMA驱动:

1)CONFIG_DMADEVICES
2)CONFIG_XILINX_DMA

5.2. DMA测试软件

以模块形式在Linux Kernel中使能如下选项,加入DMA测试软件:

1)CONFIG_XILINX_CDMATEST=m
2)CONFIG_XILINX_DMATEST=m

5.3. DMA测试软件

如果想看软件使用的内存属性,比如是否cache,可以在Linux Kernel中使能如下选项。Linux会在目录/sys/kernel/debug/kernel_page_tables下导出内存页表信息。驱动打印使用的内存地址,再结合内存页表信息,可以确认内存属性。

1)CONFIG_ARM64_PTDUMP_CORE=y
2)CONFIG_ARM64_PTDUMP_DEBUGFS=y

5.4. DMA的设备树

如下修改system-user.dtsi。

/include/ "system-conf.dtsi"
/ {
cdmatest_1: cdmatest@1 {
compatible ="xlnx,axi-cdma-test-1.00.a";
dmas = ;
dma-names = "cdma";
} ;

axidmatest_1: axidmatest@1 {
compatible ="xlnx,axi-dma-test-1.00.a";
dmas = &axi_dma_0 1>;
dma-names = "axidma0", "axidma1";
} ;
};

/* dma-coherent; */
&psu_axi_cdma_0 {
status = "okay";
dma-coherent;
};

/* dma-coherent; */
&axi_dma_0 {
status = "okay";
dma-coherent;
};

设备树节点psu_axi_cdma_0,axi_dma_0,在Petalinux自动生成的pl.dtsi里定义。

如果不使用Petalinux,以此为模板,增加设备树节点。

5.5. DMA测试软件编译结果

编译Linux后,DMA测试软件以内核模块的文件存在。

/lib/modules/4.19.0/kernel/drivers/dma/xilinx/cdmatest.ko
/lib/modules/4.19.0/kernel/drivers/dma/xilinx/axidmatest.ko

6. 测试过程 6.1. 没有使能CCI cache同步功能 6.1.1. CDMA 测试

# insmod cdmatest.ko
[ 98.016731] xilinx_cdmatest_probe()-619: Begin.
[ 98.040884] cdmatest: Started 1 threads using dma3chan0
[ 98.094364] xilinx-vdma a0001000.dma: Channel (____ptrval____) has errors 10, cdr 788c0000 tdr 788c0000
[ 98.227925] dma3chan0-copy0: dstbuf[0x8] not copied! Expected d7, got 37
[ 98.238618] dma3chan0-copy0: dstbuf[0x9] not copied! Expected d6, got 36
[ 98.245314] dma3chan0-copy0: dstbuf[0xa] not copied! Expected d5, got 35
......
[ 98.434642] dma3chan0-copy0: dstbuf[0x26] not copied! Expected d9, got 39
[ 98.441429] dma3chan0-copy0: dstbuf[0x27] not copied! Expected d8, got 38
[ 98.448210] dma3chan0-copy0: 20 errors suppressed
[ 98.452908] dma3chan0-copy0: #0: 52 errors with
[ 98.456908] src_off=0x8 dst_off=0x8 len=0x34
[ 98.523180] xilinx-vdma a0001000.dma: Channel (____ptrval____) has errors 100, cdr 788c0000 tdr 788c0000
[ 101.606407] dma3chan0-copy0: #1: test timed out

6.1.2. AXI-DMA 测试

# insmod axidmatest.ko
[ 392.529420] dmatest: Started 1 threads using dma2chan0 dma2chan1
[ 392.665889] xilinx-vdma a0010000.dma: Channel (____ptrval____) has errors 10, cdr 6fcb0000 tdr 6fcb0500
[ 393.729538] xilinx-vdma a0010000.dma: Cannot start channel (____ptrval____): 10009
[ 394.806248] dma2chan0-dma2c: #0: tx test timed out
[ 394.953756] xilinx-vdma a0010000.dma: Channel (____ptrval____) has errors 10, cdr 6fcb0580 tdr 6fcb0a80

6.2. 使能CCI cache同步功能 6.2.1. GPIO 初始化

# =====================================================
# gpio0_hpc0_awcache, 0xa0002000, AWCACHE[3:0] 1111
devmem 0xa0002004
devmem 0xa0002004 32 0x0
devmem 0xa0002004
devmem 0xa0002000 32 0xf
devmem 0xa0002000

# gpio1_hpc0_awprot, 0xa0003000, AWPROT
# AxPROT[1] ,0,secure transactions, standalone
# AxPROT[1] ,1,non-secure transactions, Linux kernel/Linux userspace.
devmem 0xa0003004
devmem 0xa0003004 32 0x0
devmem 0xa0003004
devmem 0xa0003000 32 0x2
devmem 0xa0003000

# gpio2_hpc0_arcache, 0xa0004000, ARCACHE[3:0] 1111
devmem 0xa0004004
devmem 0xa0004004 32 0x0
devmem 0xa0004004
devmem 0xa0004000 32 0xf
devmem 0xa0004000

# gpio3_hpc0_arprot, 0xa0003000, ARPROT
# AxPROT[1] ,0,secure transactions, standalone
# AxPROT[1] ,1,non-secure transactions, Linux kernel/Linux userspace.
devmem 0xa0005004
devmem 0xa0005004 32 0x0
devmem 0xa0005004
devmem 0xa0005000 32 0x2
devmem 0xa0005000

6.2.2. CDMA 测试

# insmod cdmatest.ko
[ 523.246063] cdmatest: Started 1 threads using dma3chan0
[ 539.926093] dma3chan0-copy0: terminating after 100 tests, 0 failures (status 0)

6.2.3. AXI-DMA 测试

# insmod axidmatest.ko
[ 210.871166] dmatest: Started 1 threads using dma1chan0 dma1chan1
[ 212.937889] dma1chan0-dma1c: terminating after 5 tests, 0 failures (status 0)




文章转载自:赛灵思中文社区论坛

推荐阅读