有一个无法忽视的事实,基础研发的突破,让这一切成为可能 ,
-------Qualcomm
好,看启动的时候 Linux是如何知道系统的内存大小
/*
该函数做了一下事情
1 : 获取内存 base 和 size
2 : 将内存信息添加到memblock子系统
@node:
1484, Why ?
下面会说
1 : 这个 node 为什么要定义为 unsigned long 类型
2 : linuxer在 Code Review 的时候为什么会接受这样的机制
@uname:
1 : memory@六0000000
下面会对该字符串进行校验, 它就是靠名字来决定是否进行下面的工作,
利用字符串匹配 platform bus 做的很好,
类似的是 CAN bus 滤波是通过ID匹配来完成的
作者说了 we are scanning memory node only,
其他node这里不是你的坑,return, 走人
看,每一个 node 就是这样展开的,Linux Kernel这块做的并不是智能,
Linux Kernel是时候该引入 Artificial intelligence 了 !
@depth:
@data:
好,那么该函数是怎么被调用的呢 ?
扫描整颗树吧,回调吧,
有类比的是 sock维护的钩子函数 实现的很优美,主要用于处理消息,后面会单独欣赏
int __init of_scan_flat_dt()
{
.....
FOR + IF 做决策, 也不看看这是在什么时机,
心里的“如果”少了,IF也少了
MSM8937平台 MSM_CCI_IRQ() 该ISR 简直是 IF依赖症了 哈哈.
它主要是对寄存器的各个位进行判断,
Register 它底层是通过 D触发器 来实现的 ! 后面单独欣赏D触发器的实现
上面 code 啰嗦了一大把,严重影响了启动的时间,
这里回调吧
rc = it(offset, pathp, depth, data);
}
好,下面看一下是谁调用了of_scan_flat_dt.
见下面的图A
*/
int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data)
{
/*
读出属性"device_type"的属性值,
上面说了这个字符串是 "memory@60000000"
*/
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *reg, *endp;
int l;
if (type == NULL) {
if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0)
return 0;
} else if (strcmp(type, "memory") != 0)
return 0;
reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
if (reg == NULL)
reg = of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
endp = reg + (l / sizeof(__be32));
pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n", uname, l, reg[0], reg[1], reg[2], reg[3]);
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
u64 base, size;
base = dt_mem_next_cell(dt_root_addr_cells, ®);
size = dt_mem_next_cell(dt_root_size_cells, ®);
if (size == 0)
continue;
pr_debug(" - %llx , %llx\n", (unsigned long long)base, (unsigned long long)size);
early_init_dt_add_memory_arch(base, size);
}
return 0;
}