2026/4/18 14:03:25
网站建设
项目流程
网站做的比较好的公司,豆瓣网网站建设,湖南政务服务网,做公司网站需要多长时间你提供的这两个函数是 PLIC 控制器中中断使能位#xff08;IE, Interrupt Enable#xff09; 的核心读写接口#xff0c;负责精准定位并操作指定上下文、指定中断块的 PLIC 使能寄存器#xff0c;我会从功能、地址计算逻辑、参数含义、使用场景四个维度拆解#xff0c;帮你…你提供的这两个函数是 PLIC 控制器中中断使能位IE, Interrupt Enable的核心读写接口负责精准定位并操作指定上下文、指定中断块的 PLIC 使能寄存器我会从功能、地址计算逻辑、参数含义、使用场景四个维度拆解帮你彻底理解一、整体功能总结plic_get_ie读取 PLIC 中「指定上下文 指定中断块」的中断使能寄存器值plic_set_ie向 PLIC 中「指定上下文 指定中断块」的中断使能寄存器写入值这两个函数是fdt_plic_context_save/restore的底层实现依赖——保存上下文时调用plic_get_ie读取使能位恢复时调用plic_set_ie写回使能位。二、核心逻辑PLIC 使能寄存器地址计算PLCI 使能寄存器的地址是基址 上下文偏移 中断块偏移代码中通过以下公式计算plic_ie plic-addr (PLIC基址) PLIC_ENABLE_BASE (使能寄存器块起始偏移) PLIC_ENABLE_STRIDE * cntxid (上下文偏移) 4 * word_index (中断块偏移)逐部分解析地址构成地址组成部分含义plic-addrPLIC 控制器在 SoC 中的物理基地址如 QEMU 中的0xC000000由设备树解析得到PLIC_ENABLE_BASEPLIC 使能寄存器块的起始偏移标准 PLIC 规范中为0x2000和你之前翻译的文档一致PLIC_ENABLE_STRIDE * cntxid每个上下文Context对应的使能寄存器块偏移-PLIC_ENABLE_STRIDE单个上下文的使能寄存器块大小标准为0x80对应 32 个中断块×4字节-cntxid上下文ID如 Hart0 的 M 态上下文0S 态上下文14 * word_index单个上下文内按 32 个中断为 1 块的偏移-word_index中断块编号如 0irq0311irq3263- 4 是因为每个中断块对应 32 位4字节寄存器地址计算示例贴合你之前翻译的文档假设PLIC 基址plic-addr 0xC000000PLIC_ENABLE_BASE 0x2000PLIC_ENABLE_STRIDE 0x80上下文IDcntxid 0Hart0 M 态中断块word_index 0irq0~31则最终地址0xC000000 0x2000 0x80*0 4*0 0xC002000和你之前翻译的文档中「上下文0的中断源#0至#31使能位地址0x002000」基址偏移完全一致。三、函数参数与返回值解析1. plic_get_ie 函数staticu32plic_get_ie(conststructplic_data*plic,u32 cntxid,u32 word_index)参数含义plicPLIC 硬件数据结构体指针包含基址、总中断数、上下文数等核心信息cntxid上下文ID区分不同 Hart/不同特权级如 Hart0 M 态0Hart0 S 态1word_index中断块编号按 32 个中断为 1 块范围 0 ~ (总中断数/32 - 1)返回值对应中断块的使能寄存器值32位每1位对应1个中断的使能状态1使能0禁用2. plic_set_ie 函数staticvoidplic_set_ie(conststructplic_data*plic,u32 cntxid,u32 word_index,u32 val)参数含义plic/cntxid/word_index和plic_get_ie完全一致定位要写入的使能寄存器val要写入的 32 位值每1位设置对应中断的使能状态1使能0禁用四、典型使用场景结合上下文保存/恢复// 示例保存 Hart0 S 态的 irq0~31 使能位structplic_data*plicplic_get_hart_data_ptr(scratch);u32 cntxidplic_get_hart_scontext(scratch);// 获取S态上下文IDu32 word_index0;// irq0~31 中断块// 读取使能位保存到缓冲区u32 enable_valplic_get_ie(plic,cntxid,word_index);enable_buf[word_index]enable_val;// 示例恢复 Hart0 S 态的 irq0~31 使能位u32 restore_valenable_buf[word_index];plic_set_ie(plic,cntxid,word_index,restore_val);五、关键注意点地址对齐4 * word_index保证了地址按 4 字节对齐RISC-V 32位寄存器要求避免非对齐访问异常volatile 关键字volatile void *plic_ie防止编译器优化寄存器读写PLIC 是硬件寄存器必须实时读写上下文ID 映射cntxid不是直接的 Hart ID而是 PLIC 为每个 Hart 的 M/S 态分配的上下文编号如 Hart0 M 态0S 态1Hart1 M 态2S 态3。关键点plic_get_ieplic_set_ie核心动作计算地址 → 读取 32 位使能寄存器值计算地址 → 写入 32 位使能寄存器值地址计算核心基址 上下文偏移 中断块偏移同 get_ie保证地址精准匹配底层依赖readl读取32位内存映射寄存器writel写入32位内存映射寄存器上层调用场景PLIC 上下文保存fdt_plic_context_savePLIC 上下文恢复fdt_plic_context_restore六、cntxid 分配规则6.1、通用分配规则最常见的场景绝大多数 PLIC 实现中上下文ID 按「Hart 编号 特权级」线性分配规则为cntxid 2 × hart_id (特权级标识)特权级标识M 态 0S 态 1示例Hart0 M 态 →2×0 0 0Hart0 S 态 →2×0 1 1Hart1 M 态 →2×1 0 2Hart1 S 态 →2×1 1 3Hart2 M 态 →2×2 0 4Hart2 S 态 →2×2 1 5这和你理解的「Hart1 M2、S3」完全一致是 OpenSBI/QEMU/Linux 中最主流的分配方式。6.2、特殊情况上下文ID 分配的灵活性PLIC 规范仅定义「每个上下文对应独立的使能/阈值寄存器」但未强制上下文ID 的分配规则部分场景会有差异仅支持 M 态的 PLIC嵌入式极简 PLIC 可能只支持 M 态此时上下文ID 直接等于 Hart ID如 Hart00、Hart11、Hart22无 S 态上下文。虚拟化场景H 扩展支持虚拟化的 PLIC 会为 VS/VU 态分配额外上下文规则变为cntxid 4 × hart_id (特权级标识)Hart0 M0、S1、VS2、VU3Hart1 M4、S5、VS6、VU7厂商自定义分配部分 SoC 厂商会按「特权级优先」分配如所有 M 态上下文在前S 态在后Hart0 M0、Hart1 M1、Hart2 M2Hart0 S3、Hart1 S4、Hart2 S56.3、代码中如何确认实际的 cntxid 映射在 OpenSBI 中无需硬编码可通过以下函数获取当前 Hart 对应特权级的 cntxidstructsbi_scratch*scratchsbi_scratch_thishart_ptr();// 获取当前 Hart M 态的 cntxidu32 m_cntxidplic_get_hart_mcontext(scratch);// 获取当前 Hart S 态的 cntxidu32 s_cntxidplic_get_hart_scontext(scratch);对于 Hart0m_cntxid通常返回 0s_cntxid返回 1对于 Hart1m_cntxid通常返回 2s_cntxid返回 3这也是你之前看到的fdt_plic_context_save/restore中通过smode选择plic_get_hart_scontext/plic_get_hart_mcontext的原因——固件已封装好 cntxid 映射无需开发者手动计算。小结关键点通用规则主流特殊场景Hart1 M 态 cntxid2符合你的理解1仅M态PLIC/4虚拟化场景Hart1 S 态 cntxid3符合你的理解无仅M态PLIC/5虚拟化场景核心建议无需硬编码通过plic_get_hart_*context获取实际 cntxid避免依赖固定数值以固件提供的接口为准简单来说在无虚拟化、支持 M/S 态的标准 PLIC 中Hart1 M2、S3 是完全正确的若涉及特殊场景以代码中plic_get_hart_*context的返回值为准即可。