| 153 | } |
| 154 | |
| 155 | auto InterruptInit(int, const char**) -> void { |
| 156 | InterruptSingleton::create(); |
| 157 | |
| 158 | // 注册中断处理函数 |
| 159 | RegisterInterrupts(); |
| 160 | |
| 161 | // 初始化 plic |
| 162 | auto [plic_addr, plic_size, ndev, context_count] = |
| 163 | KernelFdtSingleton::instance().GetPlic().value(); |
| 164 | VirtualMemorySingleton::instance() |
| 165 | .MapMMIO(plic_addr, plic_size) |
| 166 | .or_else([](Error err) -> Expected<void*> { |
| 167 | klog::Err("Failed to map PLIC MMIO: {}", err.message()); |
| 168 | while (true) { |
| 169 | cpu_io::Pause(); |
| 170 | } |
| 171 | return std::unexpected(err); |
| 172 | }); |
| 173 | InterruptSingleton::instance().InitPlic(plic_addr, ndev, context_count); |
| 174 | |
| 175 | // 设置 trap vector |
| 176 | auto success = |
| 177 | cpu_io::Stvec::SetDirect(reinterpret_cast<uint64_t>(trap_entry)); |
| 178 | if (!success) { |
| 179 | klog::Err("Failed to set trap vector"); |
| 180 | } |
| 181 | |
| 182 | // 开启 Supervisor 中断 |
| 183 | cpu_io::Sstatus::Sie::Set(); |
| 184 | |
| 185 | // 开启内部中断 |
| 186 | cpu_io::Sie::Ssie::Set(); |
| 187 | |
| 188 | // 开启外部中断 |
| 189 | cpu_io::Sie::Seie::Set(); |
| 190 | |
| 191 | // 通过统一接口注册串口外部中断(先注册 handler,再启用 PLIC) |
| 192 | auto serial_irq = |
| 193 | std::get<2>(KernelFdtSingleton::instance().GetSerial().value()); |
| 194 | InterruptSingleton::instance() |
| 195 | .RegisterExternalInterrupt(serial_irq, cpu_io::GetCurrentCoreId(), 1, |
| 196 | InterruptDelegate::create<SerialIrqHandler>()) |
| 197 | .or_else([](Error err) -> Expected<void> { |
| 198 | klog::Err("Failed to register serial IRQ: {}", err.message()); |
| 199 | return std::unexpected(err); |
| 200 | }); |
| 201 | |
| 202 | // 通过统一接口注册 virtio-blk 外部中断 |
| 203 | auto& blk_driver = VirtioDriverSingleton::instance(); |
| 204 | auto blk_irq = blk_driver.GetIrq(); |
| 205 | if (blk_irq != 0) { |
| 206 | InterruptSingleton::instance() |
| 207 | .RegisterExternalInterrupt( |
| 208 | blk_irq, cpu_io::GetCurrentCoreId(), 1, |
| 209 | InterruptDelegate::create<VirtioBlkIrqHandler>()) |
| 210 | .or_else([blk_irq](Error err) -> Expected<void> { |
| 211 | klog::Err("Failed to register virtio-blk IRQ {}: {}", blk_irq, |
| 212 | err.message()); |
no test coverage detected