1use aarch64_cpu::registers::*;
2use lazy_static::lazy_static;
3
4pub const ICH_HCR_EL2_INIT: u64 = (ICH_HCR_EL2::En.mask << ICH_HCR_EL2::En.shift)
5 + (ICH_HCR_EL2::vSGIEOICount.mask << ICH_HCR_EL2::vSGIEOICount.shift)
6 + (ICH_HCR_EL2::DVIM.mask << ICH_HCR_EL2::DVIM.shift);
7
8const ICH_LR_PRIORITY_WIDTH: u64 = 8;
10
11pub const ICH_HCR_EL2_NS_MASK: u64 = (ICH_HCR_EL2::UIE.mask << ICH_HCR_EL2::UIE.shift)
12 | (ICH_HCR_EL2::LRENPIE.mask << ICH_HCR_EL2::LRENPIE.shift)
13 | (ICH_HCR_EL2::NPIE.mask << ICH_HCR_EL2::NPIE.shift)
14 | (ICH_HCR_EL2::VGrp1DIE.mask << ICH_HCR_EL2::VGrp1DIE.shift)
15 | (ICH_HCR_EL2::VGrp1EIE.mask << ICH_HCR_EL2::VGrp1EIE.shift)
16 | (ICH_HCR_EL2::VGrp0DIE.mask << ICH_HCR_EL2::VGrp0DIE.shift)
17 | (ICH_HCR_EL2::VGrp0EIE.mask << ICH_HCR_EL2::VGrp0EIE.shift)
18 | (ICH_HCR_EL2::TDIR.mask << ICH_HCR_EL2::TDIR.shift);
19
20const ICH_HCR_EL2_EOI_COUNT_WIDTH: usize = 5;
21pub const ICH_HCR_EL2_EOI_COUNT_MASK: u64 =
22 ((!0u64) >> (64 - ICH_HCR_EL2_EOI_COUNT_WIDTH)) << ICH_HCR_EL2::EOIcount.shift;
23
24const MAX_SPI_ID: u64 = 1019;
25
26const MIN_EPPI_ID: u64 = 1056;
27const MAX_EPPI_ID: u64 = 1119;
28
29const MIN_ESPI_ID: u64 = 4096;
30const MAX_ESPI_ID: u64 = 5119;
31
32const MIN_LPI_ID: u64 = 8192;
33
34#[allow(dead_code)]
35pub struct GicFeatures {
36 pub nr_lrs: usize,
37 pub nr_aprs: usize,
38 pub pri_res0_mask: u64,
39 pub max_vintid: u64,
40 pub ext_range: bool,
41}
42
43lazy_static! {
44 pub static ref GIC_FEATURES: GicFeatures = {
45 trace!("read gic features");
46 let nr_lrs = ICH_VTR_EL2.read(ICH_VTR_EL2::ListRegs) as usize;
47 trace!("nr_lrs (LIST) {}", nr_lrs);
48 let id = ICH_VTR_EL2.read(ICH_VTR_EL2::IDbits);
49 let max_vintid = if id == 0 {
50 (1u64 << 16) - 1
51 } else {
52 (1u64 << 24) - 1
53 };
54 trace!("id {} max_vintid {}", id, max_vintid);
55 let pre = ICH_VTR_EL2.read(ICH_VTR_EL2::PREbits) + 1;
56 let nr_aprs = (1 << (pre - 5)) - 1;
57 trace!("pre {}, nr_aprs {}", pre, nr_aprs);
58 let pri = ICH_VTR_EL2.read(ICH_VTR_EL2::PRIbits) + 1;
59 let pri_res0_mask = (1u64 << (ICH_LR_PRIORITY_WIDTH - pri)) - 1;
60 trace!("pri {} pri_res0_mask {}", pri, pri_res0_mask);
61 let ext_range = ICC_CTLR_EL1.read(ICC_CTLR_EL1::ExtRange) != 0;
62 trace!("icc_ctlr ext_range {}", ext_range);
63 GicFeatures {
64 nr_lrs,
65 nr_aprs,
66 pri_res0_mask,
67 max_vintid,
68 ext_range,
69 }
70 };
71}
72
73pub fn nr_lrs() -> usize {
74 GIC_FEATURES.nr_lrs
75}
76
77pub fn nr_aprs() -> usize {
78 GIC_FEATURES.nr_aprs
79}
80
81pub fn pri_res0_mask() -> u64 {
82 GIC_FEATURES.pri_res0_mask
83}
84
85pub fn set_lr(i: usize, val: u64) {
86 match i {
87 0 => ICH_LR0_EL2.set(val),
88 1 => ICH_LR1_EL2.set(val),
89 2 => ICH_LR2_EL2.set(val),
90 3 => ICH_LR3_EL2.set(val),
91 4 => ICH_LR4_EL2.set(val),
92 5 => ICH_LR5_EL2.set(val),
93 6 => ICH_LR6_EL2.set(val),
94 7 => ICH_LR7_EL2.set(val),
95 8 => ICH_LR8_EL2.set(val),
96 9 => ICH_LR9_EL2.set(val),
97 10 => ICH_LR10_EL2.set(val),
98 11 => ICH_LR11_EL2.set(val),
99 12 => ICH_LR12_EL2.set(val),
100 13 => ICH_LR13_EL2.set(val),
101 14 => ICH_LR14_EL2.set(val),
102 15 => ICH_LR15_EL2.set(val),
103 _ => {}
104 }
105}
106
107pub fn set_ap0r(i: usize, val: u64) {
108 match i {
109 0 => ICH_AP0R0_EL2.set(val),
110 1 => ICH_AP0R1_EL2.set(val),
111 2 => ICH_AP0R2_EL2.set(val),
112 3 => ICH_AP0R3_EL2.set(val),
113 _ => {}
114 }
115}
116
117pub fn set_ap1r(i: usize, val: u64) {
118 match i {
119 0 => ICH_AP1R0_EL2.set(val),
120 1 => ICH_AP1R1_EL2.set(val),
121 2 => ICH_AP1R2_EL2.set(val),
122 3 => ICH_AP1R3_EL2.set(val),
123 _ => {}
124 }
125}
126
127pub fn get_lr(i: usize) -> u64 {
128 match i {
129 0 => ICH_LR0_EL2.get(),
130 1 => ICH_LR1_EL2.get(),
131 2 => ICH_LR2_EL2.get(),
132 3 => ICH_LR3_EL2.get(),
133 4 => ICH_LR4_EL2.get(),
134 5 => ICH_LR5_EL2.get(),
135 6 => ICH_LR6_EL2.get(),
136 7 => ICH_LR7_EL2.get(),
137 8 => ICH_LR8_EL2.get(),
138 9 => ICH_LR9_EL2.get(),
139 10 => ICH_LR10_EL2.get(),
140 11 => ICH_LR11_EL2.get(),
141 12 => ICH_LR12_EL2.get(),
142 13 => ICH_LR13_EL2.get(),
143 14 => ICH_LR14_EL2.get(),
144 15 => ICH_LR15_EL2.get(),
145 _ => unreachable!(),
146 }
147}
148
149pub fn get_ap0r(i: usize) -> u64 {
150 match i {
151 0 => ICH_AP0R0_EL2.get(),
152 1 => ICH_AP0R1_EL2.get(),
153 2 => ICH_AP0R2_EL2.get(),
154 3 => ICH_AP0R3_EL2.get(),
155 _ => unreachable!(),
156 }
157}
158
159pub fn get_ap1r(i: usize) -> u64 {
160 match i {
161 0 => ICH_AP1R0_EL2.get(),
162 1 => ICH_AP1R1_EL2.get(),
163 2 => ICH_AP1R2_EL2.get(),
164 3 => ICH_AP1R3_EL2.get(),
165 _ => unreachable!(),
166 }
167}
168
169pub fn valid_vintid(intid: u64) -> bool {
170 if intid <= MAX_SPI_ID || (intid >= MIN_LPI_ID && intid <= GIC_FEATURES.max_vintid) {
172 return true;
173 }
174
175 if GIC_FEATURES.ext_range {
180 return (intid >= MIN_EPPI_ID && intid <= MAX_EPPI_ID)
181 || (intid >= MIN_ESPI_ID && intid <= MAX_ESPI_ID);
182 }
183
184 false
185}