修网(AXI Ethernet)

故障现象 今日发现我之前搭建的基于Rocket Chip的SoC,在U-Boot中网卡工作,但Linux中网卡一直无法工作。并发现经常在Linux中使用ip link set eth0 up在看到dmesg输出3行网卡开启信息后系统就卡死,并在reset核心后U-boot(XIP)载入到开始访问DRAM的位置就停下。看起来像是AXI总线上(因为我没有进行Reset)有请求在我reset期间没有完成,这大概可以说明AXI总线上发了一些核的Slave无法处理的请求。 起初我怀疑问题有一部分和中断有关,因为U-Boot没有使用中断,但通过检查/proc/interrupts发现连接在PLIC上两个网卡的中断号都能在set eth0 up后出现多次中断。然后看了下Linux的Documentation中的设备树相关部分,发现我的网卡中断和DMA中断设置不对(要求把DMA中断也放在网卡中断中,但实测是等价的),修改后问题依旧,按照一个别人能工作的设备树写法修改后问题依旧。 而继续搜索相关资料发现,别人遇到的问题多数都是PHY相关。然而我使用的是SFP接口的1000BaseX,AXI Ethernet会自己实例化一个PHY,并不是外置的。 解决方法 后来我对比了我的SoC和别人的SoC,发现我拖出来的AXI DMA IP核的Memory Map Data…

用Linux resctrl玩x86 CPU上的L3 CAT

最近基于Verilator框架写了一个SoC仿真器,用C++实现了AXI接口以便软件定义MMIO。然而写完后运行发现,它的速度确实比FPGA要慢上非常多,FPGA上几秒钟完成的事情用Verilator仿真可能要跑几分钟才能跑出来。而RTL仿真是对于CPU的Cache压力很大的应用场景,因此就玩了下Linux的resctrl进行测试。方便后续选购CPU。 Linux resctrl已经支持Intel和AMD处理器中的许多技术。包括常见到的用来共享隔离Cache缓解侧信道的Intel CAT技术。然而我手里的Intel 12900K通过查看/proc/cpuinfo发现它只支持L2 CAT。而自己的AMD 5800X却可以支持L3 CAT,因此就用它进行了测试。而resctrl的配置主要参考了User Interface for Resource Control feature。 首先,对于Kernel v5.0以上,需要在config中打开CONFIG_X86_CPU_RESCTRL。Debian已经默认打开。 然后,挂载resctrl文件系统: sudo mount…

Xilinx Block Memory Generator踩坑小记

最近在用Verilator自研软件定义AXI Slave来实现SoC上设备的模拟,于是把Xilinx的Block Memory Generator当做了一个ground truth进行研究,于是就发现了一个会导致aw/w通道死锁的小坑。 复位后Master直接拉高awvalid和wvalid,则Slave不会拉高awready。但实际上Slave已经开始接收数据。 同时由于Block Memory Generator的AXI接口没有判断wlast是否符合要求,而Master一直到传输结束都不知道Slave已经接受了数据,导致一直没有拉高bready,就会导致aw/w通道死锁。 解决方法:Master在复位后的下个周期再进行操作。且AXI的Spec也要求Master在复位时应拉低ARVALID, AWVALID, WVALID。

Xilinx MIG的ECC内存踩坑小记

最近在某灵车7K325T FPGA上搭SoC,由于该灵车开发板有9个8bit DDR3组成72bit,因此就打算尝试一下ECC内存。 调试过程中遇到以下问题: 1. 开启ECC后init_calib_complete不拉高 init_calib_complete不拉高意味着内存train失败。最后发现是ddr3的dm信号在ECC开启时默认是关闭的,而我们需要将对应引脚手动拉低为0。修改后恢复。 2. AXI接口上的RRESP出现2’b10,即SLAVE ERROR。 在开启ECC后如果读取未曾写入的内存地址,会由于ECC bit没有更新导致出现ECC校验失败。在使用过程中确保该地址写入过即可。 神奇的是,我用Chipyard生成的BOOM核接到开启ECC的MIG上,如果跳转到一个没有写指令的地址时,Exception Code为2,即Illegal instruction,并非Instruction access fault。

新手的Vivado Block Design踩坑小记

最近在使用Vivado的Block Design搭建SoC,由于许多东西的User Guide不知道去哪找,因此在这里整理了一下自己作为新手使用Block Design踩过的坑。 1. 需要Create HDL Wrapper 在BD搭建完成后,点击右键选Create HDL Wrapper,然后就可以作为Top或是在别的模块中例化了。 2. 无法将System Verilog作为模块 遇到一个大问题就是自己写的System Verilog模块怎么都无法加入。后来查阅UG994发现直到Vivado 2021.2依然不支持将System Verilog作为Block…

使用nandsim模拟超过64G的大容量MTD设备

最近做毕设项目需要模拟mtd设备,并对yaffs进行相关测试。而由于要求模拟1TB容量的mtd设备,而若使用block2mtd,由于它的page size为1B大小,无法进行yaffs的挂载。 后来同学发现了Linux Kernel自带了nandsim模块,我们可以模拟一个块设备。且这个模块启动的时候可以通过overridesize参数设置整个mtd的大小为所选模拟设备的erase_size为2的整数幂。 但我们实测发现,如果overridesize设置过大,会报出以下错误: ➜ sudo modprobe nandsim first_id_byte=0x98 second_id_byte=0xd7 third_id_byte=0x94 fourth_id_byte=0x32 overridesize=20 insmod: ERROR: could not…

修好了D1板板使用Clang编译内核的问题,错误的Variables in Specified Registers用法

最近在修D1板板的驱动。遇到一些很迷惑的问题。 GCC编译的D1内核是好的,Clang不开LTO的内核是坏的,Clang编译的LTO THIN的内核是坏的,Clang编译的LTO Full内核勉强能用,Clang编译的LTO Full+CFI的内核是坏的。 但由于我们科研需要必须要使用Clang LTO+CFI,因此必须要保证能跑通开启了LTO和CFI的Kernel。 上述勉强能用的内核网卡还出现了异常的延迟、丢包、DUP。且从板子上ping外部延迟恒定为1s,而从外部ping板子延迟恒定为2s。而IPv6甚至完全不可用。 而勉强能用的内核上的SD卡,挂载上去写完文件再卸载后,接到别的电脑上挂载,却出现了文件系统损坏的情况。 而后来,经过2老师测试勉强能用的内核上的网卡驱动,发现以下问题: 经研究,clang编译的d1 linux,发包时,如果同时收到了包(比如别人发的广播包),那么发出去的包部分字节会被覆盖为收到的包 因此,我开始怀疑该问题是访问IO时Cache一致性出了问题,我就把目光从驱动本身转向了内核里维护Cache一致性的相关代码。 后来,我发现了一个这样的函数: void sbi_dma_sync(unsigned long start,…

AMD Zen 2/3处理器上的迷惑现象

今天在实验室装了一台AMD Ryzen 5700G的机器,想看看和自己寝室里放的AMD Ryzen 5800X性能差距多少,考虑到架构相同仅L3 Cache大小不同,因此就进行了一个简单的循环测试来看看单核Turbo Boost性能差距有多大。 实验室的5700G机器上安装了Ubuntu 21.04(考虑到20.04目前内核版本为5.4,无法支持Zen 3的一些电源管理特性,而实验室同学喜欢用Ubuntu),而我自己台式机则是滚的Debian sid。 两台机器自带的编译器如下(后续已经发现只与编译器有关): 实验室的5700G:gcc version 10.3.0 (Ubuntu 10.3.0-1ubuntu1) 寝室的5800X:gcc…

解决Clang+LLVM编译的Kernel多余.LBB符号导致Call Trace不方便查阅的问题

最近因为科研需求需要在全志D1开发板做性能的Evaluation,但是这个开发板的驱动用GCC编译是正常,而使用Clang+LLVM编译时存在许多问题,SD卡、网卡、USB全都有问题,因此考虑自己做一些修复。 但是由于硬件不方便在QEMU模拟,开发板的调试全靠串口输出,因此比较困难,但是一个大问题是LLVM编译的内核多了许多.LBB符号,导致Call Trace大概会长这样: [ 2.666348] [<ffffffff80004ecc>] .LBB2_1+0x20/0x2c [ 2.671152] [<ffffffff808f2c64>] dump_stack_lvl+0x4a/0x66 [ 2.676562] [<ffffffff808f2c98>] .LBB4_1+0x10/0x18 [ 2.681360] [<ffffffff808f27ce>]…