我仍在寻找的缺失信息是: 1.当获取内存映射GIC的基地址时,我理解我需要读取CBAR; 但是没有一篇文档说明CBAR中的位(2个PERIPHBASE值)应如何排列以获得最终的GIC基地址 2.通过GICD_SGIR寄存器发送SGI时,我应选择哪一个0到15之间的中断ID?是否重要? 3.通过GICD_SGIR寄存器发送SGI时,我如何告诉其他核心从哪里开始执行?
4. 如果我的代码由U-BOOT引导程序加载,这会对上下文产生什么影响?
Cortex-A系列程序员指南v3.0(在此处找到:link)在章节22.5.2(Linux中的SMP引导,第271页)中如下所述:
当主核正在启动时,次要核将处于待机状态,并使用WFI指令。它(主核)将向次要核提供启动地址,并使用Inter-Processor Interrupt(IPI)唤醒它们,这意味着通过GIC发送的SGI信号
Linux是如何做到的?文档S没有提供关于“它将向次要核提供启动地址”的其他详细信息。
我的挫败感越来越强,我将非常感谢您的答案。 非常感谢您的帮助!
额外的细节
我使用的文档:
- ARMv7-A&R体系结构参考手册
- Cortex-A15 TRM(技术参考手册)
- Cortex-A15 MPCore TRM
- Cortex-A系列程序员指南v3.0
- GICv2架构规范
到目前为止,我已经完成了以下工作:
- UBOOT将我加载到0x40008000;我设置了转换表(TTBs),相应地编写了TTBR0和TTBCR,并将0x40008000映射到0x8000_0000(2GB),因此我还启用了MMU
- 设置了自己的异常处理程序
- 我在串行(ODROID-XU上的UART2)上获得了Printf功能
所有上述内容似乎都正常工作。
现在我正在尝试做的是:
- 获取GIC基地址 => 目前我读取CBAR,然后使用其值与0xFFFF8000进行AND(&),并将其用作GIC基地址,尽管我几乎确定这是不正确的
- 通过写入值为0x1的GICD_CTLR来启用距离GIC基地址偏移量为0x1000的GIC分配器
- 使用以下参数构建SGI:组= 0,ID = 0,TargetListFilter =“除我之外的所有CPU”,并通过GICD_SGIR GIC寄存器发送它(写入)
- 由于我没有为其他核心传递任何执行起始地址,因此在所有这些操作之后什么都不会发生
....更新....
我开始查看Linux内核和QEMU源代码以寻找答案。以下是我发现的内容(如果我错了,请纠正我):
- 当开机时,所有核心都从复位向量开始执行
- 一个软件(固件)组件在次要核心上执行WFI和一些其他代码,这些代码将作为协议在这些次要核心和主核心之间起作用,当后者再次想要唤醒它们时
- 例如,在板上使用的协议如下:
**(1)** 次要核心进入WFI,然后
**(2)** 主核心发送SGI以唤醒它们
**(3)** 它们检查地址(0x40 + 0x10 * coreid)处的值是否非空;
**(4)** 如果它不为空,它们将其用作要跳转到的地址(执行BX)
**(5)** 否则,它们重新进入待机状态,重新执行WFI
**(6)** 所以,如果我有一张EnergyCore ECX-1000板,我应该使用我想要每个核心跳转到的地址写入(0x40 + 0x10 * coreid),并发送一个SGI
问题:
- 1. 这是哪个软件组件执行的?是我在SD卡上编写的BL1二进制文件还是U-BOOT?
- 2. 据我所知,这种软件协议因板而异。是这样吗,还是只取决于底层处理器?
- 3. 在哪里可以找到关于选择的ARM板的此协议信息? - 我可以在官方ARM网站或板网页上找到吗?