Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit caf42c8

Browse files
committed
bugfix:gicr bug
1 parent b6dfcc3 commit caf42c8

File tree

3 files changed

+90
-26
lines changed

3 files changed

+90
-26
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ tock-registers = "0.8"
1414
bitflags = "2.0"
1515
cfg-if = "1.0"
1616
aarch64-cpu = "9.3"
17+
log = "0.4"
18+
19+
[features]
20+
el2 = []

src/gic_v2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ impl GenericArmGic for GicV2 {
232232

233233
/// Enables the interrupt with the given ID.
234234
fn enable_interrupt(&mut self, intid: IntId) {
235+
// log::trace!("enable private interrupt {} ", intid.0);
235236
let index = intid.0 / 32;
236237
let bit = 1 << (intid.0 % 32);
237238
self.gicd.regs().ISENABLER[index].set(bit);

src/gic_v3.rs

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! The official documentation: <https://developer.arm.com/documentation/ihi0048/latest/>
44
55
use aarch64_cpu::registers::MPIDR_EL1;
6+
use log::{debug, info,trace};
67
use core::hint::spin_loop;
78
use core::ptr::NonNull;
89
use tock_registers::interfaces::{Readable, Writeable};
@@ -250,13 +251,10 @@ impl GicDistributor {
250251
for i in (IntId::SPI_START..self.support_irqs).step_by(32) {
251252
self.regs().ICACTIVER[i / 32].set(u32::MAX);
252253
self.regs().ICENABLER[i / 32].set(u32::MAX);
254+
self.regs().ICPENDR[i / 32].set(u32::MAX);
253255
}
254256

255-
// Enable affinity routing and group1
256-
self.regs()
257-
.CTLR
258-
.set((GicdCtlr::ARE_S | GicdCtlr::EnableGrp1NS).bits());
259-
self.wait_rwp();
257+
260258

261259
// Set all global interrupts to current cpu.
262260
let mpidr: u64 = MPIDR_EL1.get() & 0xff00ffffff;
@@ -270,6 +268,10 @@ impl GicDistributor {
270268
// Set external interrupts to target cpu 0
271269
self.regs().IROUTERnE[i].set(Self::mpidr_to_affinity_level(mpidr));
272270
}
271+
272+
// Enable affinity routing and group1
273+
self.regs().CTLR.set((GicdCtlr::ARE_S | GicdCtlr::EnableGrp1NS).bits());
274+
self.wait_rwp();
273275
}
274276

275277
/// Configures the trigger type for the interrupt with the given ID.
@@ -289,6 +291,31 @@ impl GicDistributor {
289291
}
290292
}
291293

294+
295+
impl core::ops::Index<usize> for GicRedistributor {
296+
type Output = GicRedistributor;
297+
298+
fn index(&self, index: usize) -> &Self::Output {
299+
if index >= 9 {
300+
panic!("GicRedistributor index out of range");
301+
}
302+
// SAFRTY: GicRedistributor has constructed with correct address,and we have checked the index
303+
unsafe { &*(self as *const GicRedistributor).add(index) }
304+
}
305+
}
306+
307+
use core::arch::asm;
308+
fn get_mpidr() -> u64 {
309+
let mpidr: u64;
310+
unsafe {
311+
asm!(
312+
"mrs {mpidr}, MPIDR_EL1", // 从 MPIDR_EL1 读取
313+
mpidr = out(reg) mpidr
314+
);
315+
}
316+
mpidr
317+
}
318+
292319
impl GicRedistributor {
293320
/// Construct a new GIC Redistributor instance from the base address.
294321
pub const fn new(base: *mut u8) -> Self {
@@ -300,6 +327,8 @@ impl GicRedistributor {
300327

301328
const fn gicr_regs(&self) -> &GicRedistributorRegs {
302329
unsafe { self.gicr_base.as_ref() }
330+
// let current_cpu_id = (get_mpidr() >> 8) as usize;
331+
// unsafe {self[current_cpu_id]}
303332
}
304333

305334
const fn sgi_regs(&self) -> &GicSgiRegs {
@@ -312,21 +341,42 @@ impl GicRedistributor {
312341
}
313342
}
314343

344+
fn get_current_cpu_id(&self) -> usize {
345+
((get_mpidr() & 0xfff) >> 8) as usize
346+
}
347+
348+
fn get_gicr_regs(&self) -> &GicRedistributorRegs {
349+
let mpidr = get_mpidr();
350+
// unsafe {trace!("this is my cpu_id {:x} gicr {:?} mpidr {:x}",self.get_current_cpu_id(),self.gicr_base.as_ptr().byte_add(self.get_current_cpu_id() * 0x2_0000 ), mpidr);}
351+
unsafe { NonNull::new(self.gicr_base.as_ptr().byte_add(self.get_current_cpu_id() * 0x2_0000 ) ).unwrap().cast().as_ref()}
352+
}
353+
354+
fn get_sgi_regs(&self) -> &GicSgiRegs {
355+
// SAFETY: Writing to this system register doesn't access memory in any way
356+
unsafe {
357+
let gicr_addr = self.gicr_base.as_ptr().byte_add(self.get_current_cpu_id() * 0x2_0000 );
358+
let sgi_base: NonNull<GicSgiRegs> =
359+
NonNull::new(gicr_addr.byte_add(SGI_OFFSET)).unwrap().cast();
360+
sgi_base.as_ref()
361+
362+
}
363+
}
364+
315365
fn redis_enable(&self) {
316-
let mut waker = self.gicr_regs().WAKER.get();
366+
let mut waker = self.get_gicr_regs().WAKER.get();
317367
// Wake up this CPU redistributor
318368
waker &= !(WakerFlags::PROCESSOR_SLEEP.bits());
319-
self.gicr_regs().WAKER.set(waker);
369+
self.get_gicr_regs().WAKER.set(waker);
320370

321-
while WakerFlags::from_bits_truncate(self.gicr_regs().WAKER.get())
371+
while WakerFlags::from_bits_truncate(self.get_gicr_regs().WAKER.get())
322372
.contains(WakerFlags::CHILDREN_ASLEEP)
323373
{
324374
spin_loop();
325375
}
326376
}
327377

328378
fn base_init(&mut self) {
329-
let typer = self.gicr_regs().TYPER.get() as usize;
379+
let typer = self.get_gicr_regs().TYPER.get() as usize;
330380
let mut ppinum = typer >> 27 & 0x1f;
331381
ppinum = match ppinum {
332382
0 => 16,
@@ -338,23 +388,24 @@ impl GicRedistributor {
338388
}
339389

340390
fn init(&mut self) {
391+
// debug!("this is my gicr {:?}",self.gicr_base.as_ptr());
341392
self.base_init();
342393
self.redis_enable();
343394
// Configure SGIs/PPIs as non-secure Group-1
344395
for i in (0..self.support_ppi + 16).step_by(32) {
345-
self.sgi_regs().IGROUPR0[i / 32].set(u32::MAX);
396+
self.get_sgi_regs().IGROUPR0[i / 32].set(u32::MAX);
346397
}
347398

348399
// Deactivate and disable all private interrupts
349400
for i in (0..self.support_ppi + 16).step_by(32) {
350-
self.sgi_regs().ICACTIVER[i / 32].set(u32::MAX);
351-
self.sgi_regs().ICENABLER[i / 32].set(u32::MAX);
401+
self.get_sgi_regs().ICACTIVER[i / 32].set(u32::MAX);
402+
self.get_sgi_regs().ICENABLER[i / 32].set(u32::MAX);
352403
}
353404

354405
// Set priority on private interrupts
355406
for i in (0..self.support_ppi + 16).step_by(4) {
356407
// once time set 4 interrupts
357-
self.sgi_regs().IPRIORITYR[i / 4].set(0xa0_a0_a0_a0);
408+
self.get_sgi_regs().IPRIORITYR[i / 4].set(0xa0_a0_a0_a0);
358409
}
359410
}
360411

@@ -365,13 +416,13 @@ impl GicRedistributor {
365416
let index = id >> 4;
366417
let bit_shift = ((id & 0xf) << 1) + 1;
367418

368-
let mut reg_val = self.sgi_regs().ICFGR[index].get();
419+
let mut reg_val = self.get_sgi_regs().ICFGR[index].get();
369420
match tm {
370421
TriggerMode::Edge => reg_val |= 1 << bit_shift,
371422
TriggerMode::Level => reg_val &= !(1 << bit_shift),
372423
}
373424

374-
self.sgi_regs().ICFGR[index].set(reg_val);
425+
self.get_sgi_regs().ICFGR[index].set(reg_val);
375426
}
376427
}
377428

@@ -403,25 +454,31 @@ impl GicV3 {
403454
// SAFETY: Writing to this system register doesn't access memory in any way.
404455
unsafe {
405456
// Enable system register access.
406-
write_sysreg!(icc_sre_el1, 0x01);
457+
write_sysreg!(icc_sre_el2, 0x01);
407458
}
408459

409460
unsafe {
410461
// Enable system register access.
411462
write_sysreg!(icc_pmr_el1, 0xf0);
412463
}
413-
414-
// SAFETY: Writing to this system register doesn't access memory in any way.
415464
unsafe {
416-
// Disable use of `ICC_PMR_EL1` as a hint for interrupt distribution, configure a write
417-
// to an EOI register to also deactivate the interrupt, and configure preemption groups
418-
// for group 0 and group 1 interrupts separately.
419-
write_sysreg!(icc_ctlr_el1, 0x00);
465+
write_sysreg!(icc_bpr1_el1, 0x0);
466+
}
467+
unsafe {
468+
write_sysreg!(icc_ctlr_el1, 0x02);
420469
}
421470

471+
// SAFETY: Writing to this system register doesn't access memory in any way.
472+
// unsafe {
473+
// // Disable use of `ICC_PMR_EL1` as a hint for interrupt distribution, configure a write
474+
// // to an EOI register to also deactivate the interrupt, and configure preemption groups
475+
// // for group 0 and group 1 interrupts separately.
476+
// write_sysreg!(icc_ctlr_el1, 0x00);
477+
// }
478+
422479
unsafe {
423480
// Enable non-secure group 1.
424-
write_sysreg!(icc_igrpen1_el1, 0x00000001);
481+
write_sysreg!(icc_igrpen1_el1, 0x01);
425482
}
426483
}
427484
}
@@ -442,9 +499,9 @@ impl GenericArmGic for GicV3 {
442499
fn enable_interrupt(&mut self, intid: IntId) {
443500
let index = intid.0 / 32;
444501
let bit = 1 << (intid.0 % 32);
445-
502+
// let mpidr = get_mpidr();
446503
if intid.is_private() {
447-
self.gicr.sgi_regs().ISENABLER[index].set(bit);
504+
self.gicr.get_sgi_regs().ISENABLER[index].set(bit);
448505
} else {
449506
self.gicd.regs().ISENABLER[index].set(bit);
450507
}
@@ -455,7 +512,7 @@ impl GenericArmGic for GicV3 {
455512
let bit = 1 << (intid.0 % 32);
456513

457514
if intid.is_private() {
458-
self.gicr.sgi_regs().ICENABLER[index].set(bit);
515+
self.gicr.get_sgi_regs().ICENABLER[index].set(bit);
459516
} else {
460517
self.gicd.regs().ICENABLER[index].set(bit);
461518
}
@@ -488,5 +545,7 @@ impl GenericArmGic for GicV3 {
488545
fn end_interrupt(&self, intid: IntId) {
489546
// SAFETY: Writing to this system register doesn't access memory in any way.
490547
unsafe { write_sysreg!(icc_eoir1_el1, intid.0 as u64) }
548+
unsafe { write_sysreg!(icc_dir_el1, intid.0 as u64) }
491549
}
492550
}
551+

0 commit comments

Comments
 (0)