鲲鹏920的DDRC

发布于 2026-07-21T21:59:44+0800

最近在研究能不能引导新版Linux和Windows,发现了用tablesfix后Linux DDRC还是会卡死,简单调了下,记录下

卡死

卡在读取DDRC的MMIO的任意地址时,通过内核printk大法发现的,依次提前返回打日志,发现第一个readl就炸了。

实验

已知ACPI里四个DDRC分别在0x94d20000 0x94d30000 0x94d40000 0x94d50000,几个版本的固件和几台机器都是一样

在UEFI Shell里读取VERSION的MMIO地址

mm 0x94d20710

发现会卡死,但

mm 0x94d30710

不会卡死

通过查看smbios type 17发现,我的一条内存插在CHANNEL 1上

于是做了以下实验:

对于D920S10 四个槽从CPU最近到最远分别是DDR4_4 DDR4_2 DDR4_3 DDR4_1

设备 内存组态 现象
D920S10 单条插在DDR4_1,显示位于CHANNEL 0 读DDRC0 DDRC1没事,读DDRC2 DDRC3卡死
D920S10 单条插在DDR4_2,显示位于CHANNEL 1 读DDRC1没事,读DDRC0 DDRC2 DDRC3卡死
D920S10 单条插在其他插槽 不亮 (一长3短)
D920S10 两条分别插DDR4_1 DDR4_3 或 DDR4_2 DDR4_4 与单插 DDR4_1/DDR4_2一致
D920S10 两条分别插DDR4_1 DDR4_2,显示两条分别位于CHANNEL 0,1 读DDRC0 DDRC1没事,读DDRC2 DDRC3卡死
W510 两条全插,显示两条分别位于CHANNEL 1,3 读DDRC0 DDRC1没事,读DDRC2 DDRC3卡死
W510 只插靠近主板那条,显示位于CHANNEL 3 读DDRC0 DDRC1没事,读DDRC2 DDRC3卡死
W510 只插远离主板那条,显示位于CHANNEL 1 读DDRC1没事,读DDRC0 DDRC2 DDRC3卡死
TK630(不同固件的D920S10) 和D920S10一致 和D920S10一致

猜测

只插CHANNEL 1的时候多少有点说法,要不要把这个逻辑实现到tablesfix里?

更新

写了个小程序读取gHisiEfiMemoryMapGuid的HOB,发现在W510上HOB给出的两个ddrc分别是channel 0和1,其中0的内存的SMBIOS显示为CHANNEL 3,原理不明

那就是说:

  • 在channel 1上只插一条的时候,就只初始化DDRC1
  • 在channel 0上只插一条,初始化DDRC 0和1,但我也写了程序看了,这时候DDRC 1的功能是空的:能正常配置DDRC_PERF_CTRL寄存器,但计数器一直是0,不会增长

因此计划实现:

  1. 通过HOB获取DDR信息
  2. 关掉所有没有插内存的DDRC,因为就算IO不会hang也用不了,没意义