Skip to content

Commit 56e927b

Browse files
rumplp1-0tr
authored andcommitted
Emulate GICv3 on macos
Signed-off-by: Djordje Lukic <[email protected]> Signed-off-by: David Gageot <[email protected]> Signed-off-by: Piotr Stankiewicz <[email protected]>
1 parent d0ac954 commit 56e927b

File tree

37 files changed

+1295
-690
lines changed

37 files changed

+1295
-690
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/arch/src/aarch64/layout.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ pub const GTIMER_HYP: u32 = 14;
8484
pub const GTIMER_VIRT: u32 = 11;
8585
pub const GTIMER_PHYS: u32 = 12;
8686

87+
pub const VTIMER_IRQ: u32 = GTIMER_VIRT + 16;
88+
8789
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
8890
#[cfg(not(feature = "efi"))]
8991
pub const MAPPED_IO_START: u64 = 1 << 30; // 1 GB

src/arch/src/aarch64/macos/gic.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use std::{boxed::Box, result};
55

6-
use super::gicv2::GICv2;
6+
use super::gicv3::GICv3;
77

88
/// Errors thrown while setting up the GIC.
99
#[derive(Debug)]
@@ -70,10 +70,7 @@ pub trait GICDevice: Send {
7070
}
7171
}
7272

73-
/// Create a GIC device.
74-
///
75-
/// It will try to create by default a GICv3 device. If that fails it will try
76-
/// to fall-back to a GICv2 device.
73+
/// Create a GICv3 device.
7774
pub fn create_gic(vcpu_count: u64) -> Result<Box<dyn GICDevice>> {
78-
GICv2::new(vcpu_count)
75+
GICv3::new(vcpu_count)
7976
}

src/arch/src/aarch64/macos/gicv3.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::{boxed::Box, result};
2+
3+
use super::gic::{Error, GICDevice};
4+
5+
type Result<T> = result::Result<T, Error>;
6+
7+
/// This is just a placeholder for building the FDT entry.
8+
/// The actual emulated GICv3 is in devices/legacy.
9+
pub struct GICv3 {
10+
/// GIC device properties, to be used for setting up the fdt entry
11+
properties: [u64; 4],
12+
13+
/// Number of CPUs handled by the device
14+
vcpu_count: u64,
15+
}
16+
17+
impl GICv3 {
18+
const SZ_64K: u64 = 0x0001_0000;
19+
20+
// Device trees specific constants
21+
const GIC_V3_MAINT_IRQ: u32 = 8;
22+
23+
/// Get the address of the GICv3 distributor.
24+
pub fn get_dist_addr() -> u64 {
25+
super::super::layout::MAPPED_IO_START - 3 * GICv3::SZ_64K
26+
}
27+
28+
/// Get the size of the GIC_v3 distributor.
29+
pub const fn get_dist_size() -> u64 {
30+
GICv3::SZ_64K
31+
}
32+
33+
/// Get the address of the GIC redistributors.
34+
pub const fn compute_redists_addr(vcpu_count: u64) -> u64 {
35+
super::super::layout::MAPPED_IO_START
36+
- 3 * GICv3::SZ_64K
37+
- GICv3::compute_redists_size(vcpu_count)
38+
}
39+
40+
pub fn get_redists_addr(&self) -> u64 {
41+
Self::compute_redists_addr(self.vcpu_count)
42+
}
43+
44+
/// Get the size of the GIC redistributors.
45+
pub const fn compute_redists_size(vcpu_count: u64) -> u64 {
46+
vcpu_count * GICv3::get_redist_size()
47+
}
48+
49+
pub fn get_redists_size(&self) -> u64 {
50+
GICv3::compute_redists_size(self.vcpu_count)
51+
}
52+
53+
pub const fn get_redist_size() -> u64 {
54+
2 * GICv3::SZ_64K
55+
}
56+
}
57+
58+
impl GICDevice for GICv3 {
59+
fn device_properties(&self) -> &[u64] {
60+
&self.properties
61+
}
62+
63+
fn vcpu_count(&self) -> u64 {
64+
self.vcpu_count
65+
}
66+
67+
fn fdt_compatibility(&self) -> &str {
68+
"arm,gic-v3"
69+
}
70+
71+
fn fdt_maint_irq(&self) -> u32 {
72+
GICv3::GIC_V3_MAINT_IRQ
73+
}
74+
75+
fn version() -> u32 {
76+
0
77+
}
78+
79+
fn create_device(vcpu_count: u64) -> Box<dyn GICDevice> {
80+
Box::new(GICv3 {
81+
properties: [
82+
GICv3::get_dist_addr(),
83+
GICv3::get_dist_size(),
84+
GICv3::compute_redists_addr(vcpu_count),
85+
GICv3::compute_redists_size(vcpu_count),
86+
],
87+
vcpu_count,
88+
})
89+
}
90+
91+
fn init_device_attributes(_gic_device: &Box<dyn GICDevice>) -> Result<()> {
92+
Ok(())
93+
}
94+
}

src/arch/src/aarch64/macos/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#[allow(clippy::new_ret_no_self)]
22
pub mod gic;
33
pub mod gicv2;
4+
pub mod gicv3;
45
pub mod regs;
6+
pub mod sysreg;

src/arch/src/aarch64/macos/sysreg.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
pub const SYSREG_OP0_SHIFT: u32 = 20;
2+
pub const SYSREG_OP0_MASK: u32 = 0x3;
3+
pub const SYSREG_OP1_SHIFT: u32 = 14;
4+
pub const SYSREG_OP1_MASK: u32 = 0x7;
5+
pub const SYSREG_CRN_SHIFT: u32 = 10;
6+
pub const SYSREG_CRN_MASK: u32 = 0xf;
7+
pub const SYSREG_CRM_SHIFT: u32 = 1;
8+
pub const SYSREG_CRM_MASK: u32 = 0xf;
9+
pub const SYSREG_OP2_SHIFT: u32 = 17;
10+
pub const SYSREG_OP2_MASK: u32 = 0x7;
11+
12+
#[macro_export]
13+
macro_rules! arm64_sys_reg {
14+
($name: tt, $op0: tt, $op1: tt, $op2: tt, $crn: tt, $crm: tt) => {
15+
pub const $name: u32 = ($op0 as u32) << SYSREG_OP0_SHIFT
16+
| ($op2 as u32) << SYSREG_OP2_SHIFT
17+
| ($op1 as u32) << SYSREG_OP1_SHIFT
18+
| ($crn as u32) << SYSREG_CRN_SHIFT
19+
| ($crm as u32) << SYSREG_CRM_SHIFT;
20+
};
21+
}
22+
23+
arm64_sys_reg!(
24+
SYSREG_MASK,
25+
SYSREG_OP0_MASK,
26+
SYSREG_OP1_MASK,
27+
SYSREG_OP2_MASK,
28+
SYSREG_CRN_MASK,
29+
SYSREG_CRM_MASK
30+
);
31+
32+
arm64_sys_reg!(SYSREG_OSLAR_EL1, 2, 0, 4, 1, 0);
33+
arm64_sys_reg!(SYSREG_OSDLR_EL1, 2, 0, 4, 1, 3);
34+
35+
arm64_sys_reg!(SYSREG_ICC_AP0R0_EL1, 3, 0, 4, 12, 8);
36+
arm64_sys_reg!(SYSREG_ICC_AP0R1_EL1, 3, 0, 5, 12, 8);
37+
arm64_sys_reg!(SYSREG_ICC_AP0R2_EL1, 3, 0, 6, 12, 8);
38+
arm64_sys_reg!(SYSREG_ICC_AP0R3_EL1, 3, 0, 7, 12, 8);
39+
arm64_sys_reg!(SYSREG_ICC_AP1R0_EL1, 3, 0, 0, 12, 9);
40+
arm64_sys_reg!(SYSREG_ICC_AP1R1_EL1, 3, 0, 1, 12, 9);
41+
arm64_sys_reg!(SYSREG_ICC_AP1R2_EL1, 3, 0, 2, 12, 9);
42+
arm64_sys_reg!(SYSREG_ICC_AP1R3_EL1, 3, 0, 3, 12, 9);
43+
arm64_sys_reg!(SYSREG_ICC_ASGI1R_EL1, 3, 0, 6, 12, 11);
44+
arm64_sys_reg!(SYSREG_ICC_BPR0_EL1, 3, 0, 3, 12, 8);
45+
arm64_sys_reg!(SYSREG_ICC_BPR1_EL1, 3, 0, 3, 12, 12);
46+
arm64_sys_reg!(SYSREG_ICC_CTLR_EL1, 3, 0, 4, 12, 12);
47+
arm64_sys_reg!(SYSREG_ICC_DIR_EL1, 3, 0, 1, 12, 11);
48+
arm64_sys_reg!(SYSREG_ICC_EOIR0_EL1, 3, 0, 1, 12, 8);
49+
arm64_sys_reg!(SYSREG_ICC_EOIR1_EL1, 3, 0, 1, 12, 12);
50+
arm64_sys_reg!(SYSREG_ICC_HPPIR0_EL1, 3, 0, 2, 12, 8);
51+
arm64_sys_reg!(SYSREG_ICC_HPPIR1_EL1, 3, 0, 2, 12, 12);
52+
arm64_sys_reg!(SYSREG_ICC_IAR0_EL1, 3, 0, 0, 12, 8);
53+
arm64_sys_reg!(SYSREG_ICC_IAR1_EL1, 3, 0, 0, 12, 12);
54+
arm64_sys_reg!(SYSREG_ICC_IGRPEN0_EL1, 3, 0, 6, 12, 12);
55+
arm64_sys_reg!(SYSREG_ICC_IGRPEN1_EL1, 3, 0, 7, 12, 12);
56+
arm64_sys_reg!(SYSREG_ICC_PMR_EL1, 3, 0, 0, 4, 6);
57+
arm64_sys_reg!(SYSREG_ICC_SGI1R_EL1, 3, 0, 5, 12, 11);
58+
arm64_sys_reg!(SYSREG_ICC_SRE_EL1, 3, 0, 5, 12, 12);
59+
60+
// ICC_CTLR_EL1 (https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/ICC-CTLR-EL1--Interrupt-Controller-Control-Register--EL1-)
61+
pub const ICC_CTLR_EL1_RSS_SHIFT: u32 = 18;
62+
pub const ICC_CTLR_EL1_A3V_SHIFT: u32 = 15;
63+
pub const ICC_CTLR_EL1_ID_BITS_SHIFT: u32 = 11;
64+
pub const ICC_CTLR_EL1_PRI_BITS_SHIFT: u32 = 8;
65+
66+
pub fn icc_reg_name(addr: u32) -> Option<&'static str> {
67+
match addr {
68+
SYSREG_ICC_IAR0_EL1 => Some("SYSREG_ICC_IAR0_EL1"),
69+
SYSREG_ICC_IAR1_EL1 => Some("SYSREG_ICC_IAR1_EL1"),
70+
SYSREG_ICC_EOIR0_EL1 => Some("SYSREG_ICC_EOIR0_EL1"),
71+
SYSREG_ICC_EOIR1_EL1 => Some("SYSREG_ICC_EOIR1_EL1"),
72+
SYSREG_ICC_AP0R0_EL1 => Some("SYSREG_ICC_AP0R0_EL1"),
73+
SYSREG_ICC_AP0R1_EL1 => Some("SYSREG_ICC_AP0R1_EL1"),
74+
SYSREG_ICC_AP0R2_EL1 => Some("SYSREG_ICC_AP0R2_EL1"),
75+
SYSREG_ICC_AP0R3_EL1 => Some("SYSREG_ICC_AP0R3_EL1"),
76+
SYSREG_ICC_AP1R0_EL1 => Some("SYSREG_ICC_AP1R0_EL1"),
77+
SYSREG_ICC_AP1R1_EL1 => Some("SYSREG_ICC_AP1R1_EL1"),
78+
SYSREG_ICC_AP1R2_EL1 => Some("SYSREG_ICC_AP1R2_EL1"),
79+
SYSREG_ICC_AP1R3_EL1 => Some("SYSREG_ICC_AP1R3_EL1"),
80+
SYSREG_ICC_ASGI1R_EL1 => Some("SYSREG_ICC_ASGI1R_EL1"),
81+
SYSREG_ICC_BPR0_EL1 => Some("SYSREG_ICC_BPR0_EL1"),
82+
SYSREG_ICC_BPR1_EL1 => Some("SYSREG_ICC_BPR1_EL1"),
83+
SYSREG_ICC_CTLR_EL1 => Some("SYSREG_ICC_CTLR_EL1"),
84+
SYSREG_ICC_DIR_EL1 => Some("SYSREG_ICC_DIR_EL1"),
85+
SYSREG_ICC_HPPIR0_EL1 => Some("SYSREG_ICC_HPPIR0_EL1"),
86+
SYSREG_ICC_HPPIR1_EL1 => Some("SYSREG_ICC_HPPIR1_EL1"),
87+
SYSREG_ICC_IGRPEN0_EL1 => Some("SYSREG_ICC_IGRPEN0_EL1"),
88+
SYSREG_ICC_IGRPEN1_EL1 => Some("SYSREG_ICC_IGRPEN1_EL1"),
89+
SYSREG_ICC_PMR_EL1 => Some("SYSREG_ICC_PMR_EL1"),
90+
SYSREG_ICC_SGI1R_EL1 => Some("SYSREG_ICC_SGI1R_EL1"),
91+
SYSREG_ICC_SRE_EL1 => Some("SYSREG_ICC_SRE_EL1"),
92+
_ => None,
93+
}
94+
}
95+
96+
pub fn sysreg_op0(sysreg: u32) -> u32 {
97+
(sysreg >> SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK
98+
}
99+
100+
pub fn sysreg_op1(sysreg: u32) -> u32 {
101+
(sysreg >> SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK
102+
}
103+
104+
pub fn sysreg_op2(sysreg: u32) -> u32 {
105+
(sysreg >> SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK
106+
}
107+
108+
pub fn sysreg_crn(sysreg: u32) -> u32 {
109+
(sysreg >> SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK
110+
}
111+
112+
pub fn sysreg_crm(sysreg: u32) -> u32 {
113+
(sysreg >> SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK
114+
}
115+
116+
pub fn is_id_sysreg(reg: u32) -> bool {
117+
sysreg_op0(reg) == 3
118+
&& sysreg_op1(reg) == 0
119+
&& sysreg_crn(reg) == 0
120+
&& sysreg_crm(reg) >= 1
121+
&& sysreg_crm(reg) < 8
122+
}

src/devices/src/legacy/aarch64/gpio.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
use std::fmt;
1111
use std::os::fd::AsRawFd;
1212
use std::result;
13-
use std::sync::{Arc, Mutex};
1413

1514
use polly::event_manager::{EventManager, Subscriber};
1615
use utils::byte_order::{read_le_u32, write_le_u32};
1716
use utils::epoll::{EpollEvent, EventSet};
1817
use utils::eventfd::EventFd;
1918

2019
use crate::bus::BusDevice;
21-
use crate::legacy::Gic;
20+
use crate::legacy::GicV3;
2221

2322
const OFS_DATA: u64 = 0x400; // Data Register
2423
const GPIODIR: u64 = 0x400; // Direction Register
@@ -74,7 +73,7 @@ pub struct Gpio {
7473
afsel: u32,
7574
// GPIO irq_field
7675
interrupt_evt: EventFd,
77-
intc: Option<Arc<Mutex<Gic>>>,
76+
intc: Option<GicV3>,
7877
irq_line: Option<u32>,
7978
shutdown_efd: EventFd,
8079
}
@@ -98,11 +97,12 @@ impl Gpio {
9897
}
9998
}
10099

101-
pub fn set_intc(&mut self, intc: Arc<Mutex<Gic>>) {
100+
pub fn set_intc(&mut self, intc: GicV3) {
102101
self.intc = Some(intc);
103102
}
104103

105104
pub fn set_irq_line(&mut self, irq: u32) {
105+
debug!("SET_IRQ_LINE (GPIO)={}", irq);
106106
self.irq_line = Some(irq);
107107
}
108108

@@ -166,7 +166,7 @@ impl Gpio {
166166

167167
fn trigger_gpio_interrupt(&self) {
168168
if let Some(intc) = &self.intc {
169-
intc.lock().unwrap().set_irq(self.irq_line.unwrap());
169+
intc.set_irq(self.irq_line.unwrap());
170170
} else if let Err(e) = self.interrupt_evt.write(1) {
171171
error!("Failed to signal used queue: {:?}", e);
172172
}

src/devices/src/legacy/aarch64/serial.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
99
use std::collections::VecDeque;
1010
use std::fmt;
11-
use std::sync::{Arc, Mutex};
1211
use std::{io, result};
1312

1413
use polly::event_manager::{EventManager, Subscriber};
@@ -17,8 +16,7 @@ use utils::epoll::{EpollEvent, EventSet};
1716
use utils::eventfd::EventFd;
1817

1918
use crate::bus::BusDevice;
20-
use crate::legacy::Gic;
21-
use crate::legacy::ReadableFd;
19+
use crate::legacy::{GicV3, ReadableFd};
2220

2321
/* Registers */
2422
const UARTDR: u64 = 0;
@@ -91,7 +89,7 @@ pub struct Serial {
9189
read_trigger: u32,
9290
out: Option<Box<dyn io::Write + Send>>,
9391
input: Option<Box<dyn ReadableFd + Send>>,
94-
intc: Option<Arc<Mutex<Gic>>>,
92+
intc: Option<GicV3>,
9593
irq_line: Option<u32>,
9694
}
9795

@@ -179,11 +177,12 @@ impl Serial {
179177
Self::new(interrupt_evt, None, None)
180178
}
181179

182-
pub fn set_intc(&mut self, intc: Arc<Mutex<Gic>>) {
180+
pub fn set_intc(&mut self, intc: GicV3) {
183181
self.intc = Some(intc);
184182
}
185183

186184
pub fn set_irq_line(&mut self, irq: u32) {
185+
debug!("SET_IRQ_LINE (SERIAL)={}", irq);
187186
self.irq_line = Some(irq);
188187
}
189188

@@ -308,7 +307,7 @@ impl Serial {
308307

309308
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
310309
if let Some(intc) = &self.intc {
311-
intc.lock().unwrap().set_irq(self.irq_line.unwrap());
310+
intc.set_irq(self.irq_line.unwrap());
312311
Ok(())
313312
} else {
314313
self.interrupt_evt.write(1)

0 commit comments

Comments
 (0)