13Gic::Gic(uint64_t gicd_base_addr, uint64_t gicr_base_addr)
14 : gicd_(gicd_base_addr), gicr_(gicr_base_addr) {
15 cpu_io::ICC_IGRPEN1_EL1::Enable::Clear();
16 cpu_io::ICC_PMR_EL1::Priority::Set();
24 cpu_io::ICC_IGRPEN1_EL1::Enable::Clear();
25 cpu_io::ICC_PMR_EL1::Priority::Set();
31auto Gic::Spi(uint32_t intid, uint32_t cpuid)
const ->
void {
32 gicd_.SetupSpi(intid, cpuid);
35auto Gic::Ppi(uint32_t intid, uint32_t cpuid)
const ->
void {
36 gicr_.SetupPpi(intid, cpuid);
39auto Gic::Sgi(uint32_t intid, uint32_t cpuid)
const ->
void {
40 gicr_.SetupSgi(intid, cpuid);
44 assert(
base_addr_ != 0 &&
"GICD base address is invalid");
52 klog::Info(
"it_lines_number {}", it_lines_number);
55 for (uint32_t i = 0; i < it_lines_number; i++) {
61 auto is = Read(Isenablern(intid / kIsEnablernSize));
62 is |= 1 << (intid % kIsEnablernSize);
63 Write(Isenablern(intid / kIsEnablernSize), is);
67 Write(kCtlr, kCtlrEnableGrp1Ns);
68 cpu_io::ICC_IGRPEN1_EL1::Enable::Set();
72 auto ic = Read(Icenablern(intid / kIcEnablernSize));
73 ic |= 1 << (intid % kIcEnablernSize);
74 Write(Icenablern(intid / kIcEnablernSize), ic);
78 auto ic = Read(Icpendrn(intid / kIcPendrnSize));
79 ic |= 1 << (intid % kIcPendrnSize);
80 Write(Icpendrn(intid / kIcPendrnSize), ic);
84 auto is = Read(Isenablern(intid / kIsEnablernSize));
85 return is & (1 << (intid % kIsEnablernSize));
89 auto shift = (intid % kIpriorityrnSize) * kIpriorityrnBits;
90 auto ip = Read(Ipriorityrn(intid / kIpriorityrnSize));
91 ip &= ~(kIpriorityrnBitsMask << shift);
93 Write(Ipriorityrn(intid / kIpriorityrnSize), ip);
97 auto shift = (intid % kIcfgrnSize) * kIcfgrnBits;
98 auto ic = Read(Icfgrn(intid / kIcfgrnSize));
99 ic &= ~(kIcfgrnBitsMask << shift);
100 ic |= config << shift;
101 Write(Icfgrn(intid / kIcfgrnSize), ic);
105 auto target = Read(Itargetsrn(intid / kItargetsrnSize));
106 target &= ~(kIcfgrnBitsMask << ((intid % kItargetsrnSize) * kItargetsrnBits));
108 Itargetsrn(intid / kItargetsrnSize),
109 target | ((1 << cpuid) << ((intid % kItargetsrnSize) * kItargetsrnBits)));
116 Write(cpuid, kCtlr, 0);
119 cpu_io::ICC_SRE_EL1::SRE::Set();
122 Write(cpuid, kIgroupr0, kIgroupr0Set);
123 Write(cpuid, kIgrpmodr0, kIgrpmodr0Clear);
128 auto waker = Read(cpuid, kWaker);
130 Write(cpuid, kWaker, waker & ~kWakerProcessorSleepMask);
132 while (Read(cpuid, kWaker) & kWakerChildrenAsleepMask) {
139 SetConfig(intid, kIcfgrnLevelSensitive);
145 SetTarget(intid, cpuid);
153 assert(
base_addr_ != 0 &&
"GICR base address is invalid");
161 cpu_io::ICC_SRE_EL1::SRE::Set();
180 auto is = Read(cpuid, kIsEnabler0);
181 is |= 1 << (intid % kIsEnabler0Size);
182 Write(cpuid, kIsEnabler0, is);
186 auto ic = Read(cpuid, kIcEnabler0);
187 ic |= 1 << (intid % kIcEnabler0Size);
188 Write(cpuid, kIcEnabler0, ic);
192 auto ic = Read(cpuid, kIcPendr0);
193 ic |= 1 << (intid % kIcPendr0Size);
194 Write(cpuid, kIcPendr0, ic);
199 auto shift = (intid % kIpriorityrnSize) * kIpriorityrnBits;
200 auto ip = Read(cpuid, Ipriorityrn(intid / kIpriorityrnSize));
201 ip &= ~(kIpriorityrnBitsMask << shift);
203 Write(cpuid, Ipriorityrn(intid / kIpriorityrnSize), ip);
207 SetPrio(intid, cpuid, 0);
209 Enable(intid, cpuid);
213 SetPrio(intid, cpuid, 0);
215 Enable(intid, cpuid);
static constexpr uint32_t kTyper
Configuration dependent Interrupt Controller Type Register, RO.
auto EnableGrp1Ns() const -> void
允许 no-sec group1 中断
auto SetTarget(uint32_t intid, uint32_t cpuid) const -> void
设置 intid 的由指定 cpu 处理
auto SetConfig(uint32_t intid, uint32_t config) const -> void
设置 intid 的属性
auto SetupSpi(uint32_t intid, uint32_t cpuid) const -> void
设置指定 SPI 中断 SPI: shared peripheral interrupt, 共享外设中断,该中断来源于外设,但是该中断可以对所有的 core 有效
auto Disable(uint32_t intid) const -> void
禁止从 Distributor 转发到 redistributor
uint64_t base_addr_
GICD 基地址
__always_inline auto Igrouprn(uint64_t n) const -> uint64_t
计算 IGROUPR 寄存器偏移
__always_inline auto Write(uint32_t off, uint32_t val) const -> void
auto SetPrio(uint32_t intid, uint32_t prio) const -> void
设置 intid 的优先级
auto Clear(uint32_t intid) const -> void
清除 intid 的中断
auto IsEnable(uint32_t intid) const -> bool
判断 intid 中断是否使能
__always_inline auto Read(uint32_t off) const -> uint32_t
static constexpr uint32_t kTyperItLinesNumberMask
static constexpr uint32_t kCtlr
auto Enable(uint32_t intid) const -> void
允许从 Distributor 转发到 redistributor
auto SetPrio(uint32_t intid, uint32_t cpuid, uint32_t prio) const -> void
设置 intid 的优先级
static constexpr uint32_t kIgrpmodr0
static constexpr uint32_t kCtlr
auto SetUp() const -> void
初始化 gicr,在多核场景使用
auto SetupPpi(uint32_t intid, uint32_t cpuid) const -> void
设置指定 PPI 中断 PPI: private peripheral interrupt, 私有外设中断,该中断来源于外设,但是该中断只对指定的 core 有效
static constexpr uint32_t kIgroupr0
uint64_t base_addr_
GICR 基地址
auto SetupSgi(uint32_t intid, uint32_t cpuid) const -> void
设置指定 SGI 中断 SGI: Software Generated Interrupt, 软件生成中断,用于处理器间通信
static constexpr uint32_t kWaker
auto Enable(uint32_t intid, uint32_t cpuid) const -> void
允许从 redistributor 转发到 CPU interface
auto Clear(uint32_t intid, uint32_t cpuid) const -> void
清除指定 cpu intid 的中断
static constexpr uint32_t kIgroupr0Set
__always_inline auto Write(uint32_t cpuid, uint32_t off, uint32_t val) const -> void
static constexpr uint32_t kIgrpmodr0Clear
__always_inline auto Read(uint32_t cpuid, uint32_t off) const -> uint32_t
static constexpr uint32_t kWakerChildrenAsleepMask
auto Disable(uint32_t intid, uint32_t cpuid) const -> void
禁止从 redistributor 转发到 CPU interface
static constexpr uint32_t kWakerProcessorSleepMask
auto Spi(uint32_t intid, uint32_t cpuid) const -> void
配置共享外设中断 (SPI)
auto Sgi(uint32_t intid, uint32_t cpuid) const -> void
配置软件生成中断 (SGI)
auto SetUp() const -> void
初始化当前 CPU 的 GIC 配置
auto Ppi(uint32_t intid, uint32_t cpuid) const -> void
配置私有外设中断 (PPI)
Gicr gicr_
Redistributor 实例
auto GetCurrentCoreId() -> size_t
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志