15 klog::Info(
"Default PLIC handler, cause: {:#x}, context: {:#x}", cause,
16 reinterpret_cast<uintptr_t
>(context));
24Plic::Plic(uint64_t dev_addr,
size_t ndev,
size_t context_count)
25 : base_addr_(dev_addr), ndev_(ndev), context_count_(context_count) {
27 klog::Info(
"Setting all interrupt priorities to 0");
28 for (
size_t source_id = 0; source_id <=
ndev_; source_id++) {
32 klog::Info(
"Disabling all interrupts for all contexts");
34 for (
size_t context_id = 0; context_id <
context_count_; context_id++) {
38 for (
size_t source_id = 0; source_id <=
ndev_; source_id++) {
44 "PLIC initialization: all interrupts disabled, priorities set to 0");
47 h = InterruptDelegate::create<DefaultPlicHandler>();
58 ClaimComplete(context_id) = source_id;
63 interrupt_handlers_[cause] = func;
67 interrupt_handlers_[cause](cause, context);
70auto Plic::Set(uint32_t hart_id, uint32_t source_id, uint32_t priority,
71 bool enable)
const ->
void {
73 SourcePriority(source_id) = priority;
76 uint32_t context_id = GetContextId(hart_id);
77 SetEnableBit(context_id, source_id, enable);
80auto Plic::Get(uint32_t hart_id, uint32_t source_id)
const
81 -> std::tuple<uint32_t, bool, bool> {
83 auto priority = SourcePriority(source_id);
86 uint32_t context_id = GetContextId(hart_id);
87 auto enabled = GetEnableBit(context_id, source_id);
90 auto pending = GetPendingBit(source_id);
92 return {priority, enabled, pending};
96 uint32_t word_index = source_id / 32;
97 uint32_t bit_index = source_id % 32;
98 uint32_t* word_addr =
reinterpret_cast<uint32_t*
>(
99 base_addr_ + kEnableBitsOffset + (context_id * kEnableSize) +
101 return (*word_addr >> bit_index) & 1;
105 bool value)
const ->
void {
106 uint32_t word_index = source_id / 32;
107 uint32_t bit_index = source_id % 32;
108 uint32_t* word_addr =
reinterpret_cast<uint32_t*
>(
109 base_addr_ + kEnableBitsOffset + (context_id * kEnableSize) +
112 *word_addr |= (1U << bit_index);
114 *word_addr &= ~(1U << bit_index);
119 return *
reinterpret_cast<uint32_t*
>(base_addr_ + kSourcePriorityOffset +
120 (source_id *
sizeof(uint32_t)));
124 uint32_t word_index = source_id / 32;
125 uint32_t bit_index = source_id % 32;
126 uint32_t* word_addr =
reinterpret_cast<uint32_t*
>(
127 base_addr_ + kPendingBitsOffset + (word_index * 4));
128 return (*word_addr >> bit_index) & 1;
132 uint32_t word_index = source_id / 32;
133 uint32_t bit_index = source_id % 32;
134 uint32_t* word_addr =
reinterpret_cast<uint32_t*
>(
135 base_addr_ + kPendingBitsOffset + (word_index * 4));
137 *word_addr |= (1U << bit_index);
139 *word_addr &= ~(1U << bit_index);
144 return *
reinterpret_cast<uint32_t*
>(base_addr_ + kContextOffset +
145 (context_id * kContextSize) +
146 kPriorityThresholdOffset);
150 return *
reinterpret_cast<uint32_t*
>(base_addr_ + kContextOffset +
151 (context_id * kContextSize) +
152 kClaimCompleteOffset);
auto Set(uint32_t hart_id, uint32_t source_id, uint32_t priority, bool enable) const -> void
设置指定中断源的使能状态
auto GetEnableBit(uint32_t context_id, uint32_t source_id) const -> bool
获取使能位寄存器中指定中断源的状态
auto Done(uint32_t source_id) const -> void
告知 Plic 已经处理了当前 IRQ
auto PriorityThreshold(uint32_t context_id) const -> uint32_t &
获取优先级阈值寄存器
auto SourcePriority(uint32_t source_id) const -> uint32_t &
获取中断源优先级寄存器
auto Which() const -> uint32_t
向 Plic 询问中断
auto GetPendingBit(uint32_t source_id) const -> bool
获取挂起位寄存器中指定中断源的状态
auto SetEnableBit(uint32_t context_id, uint32_t source_id, bool value) const -> void
设置使能位寄存器中指定中断源的状态
auto ClaimComplete(uint32_t context_id) const -> uint32_t &
获取声明/完成寄存器
auto Get(uint32_t hart_id, uint32_t source_id) const -> std::tuple< uint32_t, bool, bool >
获取指定中断源的状态信息
auto Do(uint64_t cause, cpu_io::TrapContext *context) -> void
执行外部中断处理
__always_inline auto GetContextId(uint32_t hart_id, uint32_t mode=1) const -> uint32_t
计算 context ID
static constexpr size_t kInterruptMaxCount
最大外部中断数量
InterruptBase::InterruptDelegate InterruptDelegate
auto SetPendingBit(uint32_t source_id, bool value) const -> void
设置挂起位寄存器中指定中断源的状态
auto RegisterInterruptFunc(uint8_t cause, InterruptDelegate func) -> void
注册外部中断处理函数
static std::array< InterruptDelegate, kInterruptMaxCount > interrupt_handlers_
外部中断处理函数数组
auto GetCurrentCoreId() -> size_t
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志