xref: /aosp_15_r20/external/crosvm/devices/src/irqchip/kvm/riscv64.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use base::errno_result;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as BaseError;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::kvm::KvmVcpu;
15*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::kvm::KvmVm;
16*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::DeviceKind;
17*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute;
18*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm;
19*bb4ee6a4SAndroid Build Coastguard Worker use kvm_sys::*;
20*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
21*bb4ee6a4SAndroid Build Coastguard Worker 
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipRiscv64;
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker const RISCV_IRQCHIP: u64 = 0x0800_0000;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_ADDR_APLIC: u64 = 0;
28*bb4ee6a4SAndroid Build Coastguard Worker 
29*bb4ee6a4SAndroid Build Coastguard Worker pub const AIA_IMSIC_BASE: u64 = RISCV_IRQCHIP;
30*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_IMSIC_SIZE: u64 = 0x1000;
31*bb4ee6a4SAndroid Build Coastguard Worker 
aia_addr_imsic(vcpu_id: u64) -> u6432*bb4ee6a4SAndroid Build Coastguard Worker pub const fn aia_addr_imsic(vcpu_id: u64) -> u64 {
33*bb4ee6a4SAndroid Build Coastguard Worker     1 + vcpu_id
34*bb4ee6a4SAndroid Build Coastguard Worker }
35*bb4ee6a4SAndroid Build Coastguard Worker 
aia_imsic_addr(hart: usize) -> u6436*bb4ee6a4SAndroid Build Coastguard Worker pub const fn aia_imsic_addr(hart: usize) -> u64 {
37*bb4ee6a4SAndroid Build Coastguard Worker     AIA_IMSIC_BASE + (hart as u64) * KVM_DEV_RISCV_IMSIC_SIZE
38*bb4ee6a4SAndroid Build Coastguard Worker }
39*bb4ee6a4SAndroid Build Coastguard Worker 
aia_imsic_size(num_harts: usize) -> u6440*bb4ee6a4SAndroid Build Coastguard Worker pub const fn aia_imsic_size(num_harts: usize) -> u64 {
41*bb4ee6a4SAndroid Build Coastguard Worker     num_harts as u64 * KVM_DEV_RISCV_IMSIC_SIZE
42*bb4ee6a4SAndroid Build Coastguard Worker }
43*bb4ee6a4SAndroid Build Coastguard Worker 
aia_aplic_addr(num_harts: usize) -> u6444*bb4ee6a4SAndroid Build Coastguard Worker pub const fn aia_aplic_addr(num_harts: usize) -> u64 {
45*bb4ee6a4SAndroid Build Coastguard Worker     AIA_IMSIC_BASE + (num_harts as u64) * KVM_DEV_RISCV_IMSIC_SIZE
46*bb4ee6a4SAndroid Build Coastguard Worker }
47*bb4ee6a4SAndroid Build Coastguard Worker pub const AIA_APLIC_SIZE: u32 = 0x4000;
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker // Connstants for get/set attributes calls.
50*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_GRP_CONFIG: u32 = 0;
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_CONFIG_MODE: u64 = 0;
53*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_CONFIG_IDS: u64 = 1;
54*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_CONFIG_SRCS: u64 = 2;
55*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_CONFIG_HART_BITS: u64 = 5;
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker pub const IMSIC_MAX_INT_IDS: u64 = 2047;
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker // CONFIG_MODE values
60*bb4ee6a4SAndroid Build Coastguard Worker const AIA_MODE_HWACCEL: u32 = 1;
61*bb4ee6a4SAndroid Build Coastguard Worker const AIA_MODE_AUTO: u32 = 2;
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_GRP_ADDR: u32 = 1;
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker const KVM_DEV_RISCV_AIA_GRP_CTRL: u32 = 2;
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker struct AiaDescriptor(SafeDescriptor);
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker impl AiaDescriptor {
try_clone(&self) -> Result<AiaDescriptor>70*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<AiaDescriptor> {
71*bb4ee6a4SAndroid Build Coastguard Worker         self.0.try_clone().map(AiaDescriptor)
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
aia_init(&self) -> Result<()>74*bb4ee6a4SAndroid Build Coastguard Worker     fn aia_init(&self) -> Result<()> {
75*bb4ee6a4SAndroid Build Coastguard Worker         let init_attr = kvm_device_attr {
76*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_CTRL,
77*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_CTRL_INIT as u64,
78*bb4ee6a4SAndroid Build Coastguard Worker             addr: 0,
79*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
80*bb4ee6a4SAndroid Build Coastguard Worker         };
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_aia_mode is pointing
83*bb4ee6a4SAndroid Build Coastguard Worker         // to a uniquely owned local, mutable variable.
84*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR, &init_attr) };
85*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
86*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
87*bb4ee6a4SAndroid Build Coastguard Worker         }
88*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
89*bb4ee6a4SAndroid Build Coastguard Worker     }
90*bb4ee6a4SAndroid Build Coastguard Worker 
get_num_ids(&self) -> Result<u32>91*bb4ee6a4SAndroid Build Coastguard Worker     fn get_num_ids(&self) -> Result<u32> {
92*bb4ee6a4SAndroid Build Coastguard Worker         let mut aia_num_ids = 0;
93*bb4ee6a4SAndroid Build Coastguard Worker         let raw_num_ids = &mut aia_num_ids as *mut u32;
94*bb4ee6a4SAndroid Build Coastguard Worker 
95*bb4ee6a4SAndroid Build Coastguard Worker         let aia_num_ids_attr = kvm_device_attr {
96*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_CONFIG,
97*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_CONFIG_IDS,
98*bb4ee6a4SAndroid Build Coastguard Worker             addr: raw_num_ids as u64,
99*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
100*bb4ee6a4SAndroid Build Coastguard Worker         };
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_num_ids is pointing
103*bb4ee6a4SAndroid Build Coastguard Worker         // to a uniquely owned local, mutable variable.
104*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_GET_DEVICE_ATTR, &aia_num_ids_attr) };
105*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
106*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
107*bb4ee6a4SAndroid Build Coastguard Worker         }
108*bb4ee6a4SAndroid Build Coastguard Worker         Ok(aia_num_ids)
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker 
get_aia_mode(&self) -> Result<u32>111*bb4ee6a4SAndroid Build Coastguard Worker     fn get_aia_mode(&self) -> Result<u32> {
112*bb4ee6a4SAndroid Build Coastguard Worker         let mut aia_mode: u32 = AIA_MODE_HWACCEL;
113*bb4ee6a4SAndroid Build Coastguard Worker         let raw_aia_mode = &mut aia_mode as *mut u32;
114*bb4ee6a4SAndroid Build Coastguard Worker         let aia_mode_attr = kvm_device_attr {
115*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_CONFIG,
116*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_CONFIG_MODE,
117*bb4ee6a4SAndroid Build Coastguard Worker             addr: raw_aia_mode as u64,
118*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
119*bb4ee6a4SAndroid Build Coastguard Worker         };
120*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_aia_mode is pointing
121*bb4ee6a4SAndroid Build Coastguard Worker         // to a uniquely owned local, mutable variable.
122*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_GET_DEVICE_ATTR, &aia_mode_attr) };
123*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
124*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
125*bb4ee6a4SAndroid Build Coastguard Worker         }
126*bb4ee6a4SAndroid Build Coastguard Worker         Ok(aia_mode)
127*bb4ee6a4SAndroid Build Coastguard Worker     }
128*bb4ee6a4SAndroid Build Coastguard Worker 
set_num_sources(&self, num_sources: u32) -> Result<()>129*bb4ee6a4SAndroid Build Coastguard Worker     fn set_num_sources(&self, num_sources: u32) -> Result<()> {
130*bb4ee6a4SAndroid Build Coastguard Worker         let raw_num_sources = &num_sources as *const u32;
131*bb4ee6a4SAndroid Build Coastguard Worker         let kvm_attr = kvm_device_attr {
132*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_CONFIG,
133*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_CONFIG_SRCS,
134*bb4ee6a4SAndroid Build Coastguard Worker             addr: raw_num_sources as u64,
135*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
136*bb4ee6a4SAndroid Build Coastguard Worker         };
137*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_aia_mode is pointing
138*bb4ee6a4SAndroid Build Coastguard Worker         // to a uniquely owned local, mutable variable.
139*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR, &kvm_attr) };
140*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
141*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
142*bb4ee6a4SAndroid Build Coastguard Worker         }
143*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
144*bb4ee6a4SAndroid Build Coastguard Worker     }
145*bb4ee6a4SAndroid Build Coastguard Worker 
set_hart_bits(&self, hart_bits: u32) -> Result<()>146*bb4ee6a4SAndroid Build Coastguard Worker     fn set_hart_bits(&self, hart_bits: u32) -> Result<()> {
147*bb4ee6a4SAndroid Build Coastguard Worker         let raw_hart_bits = &hart_bits as *const u32;
148*bb4ee6a4SAndroid Build Coastguard Worker         let kvm_attr = kvm_device_attr {
149*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_CONFIG,
150*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
151*bb4ee6a4SAndroid Build Coastguard Worker             addr: raw_hart_bits as u64,
152*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
153*bb4ee6a4SAndroid Build Coastguard Worker         };
154*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_aia_mode is pointing
155*bb4ee6a4SAndroid Build Coastguard Worker         // to a uniquely owned local, mutable variable.
156*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR, &kvm_attr) };
157*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
158*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
159*bb4ee6a4SAndroid Build Coastguard Worker         }
160*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
161*bb4ee6a4SAndroid Build Coastguard Worker     }
162*bb4ee6a4SAndroid Build Coastguard Worker 
set_aplic_addrs(&self, num_vcpus: usize) -> Result<()>163*bb4ee6a4SAndroid Build Coastguard Worker     fn set_aplic_addrs(&self, num_vcpus: usize) -> Result<()> {
164*bb4ee6a4SAndroid Build Coastguard Worker         /* Set AIA device addresses */
165*bb4ee6a4SAndroid Build Coastguard Worker         let aplic_addr = aia_aplic_addr(num_vcpus);
166*bb4ee6a4SAndroid Build Coastguard Worker         let raw_aplic_addr = &aplic_addr as *const u64;
167*bb4ee6a4SAndroid Build Coastguard Worker         let kvm_attr = kvm_device_attr {
168*bb4ee6a4SAndroid Build Coastguard Worker             group: KVM_DEV_RISCV_AIA_GRP_ADDR,
169*bb4ee6a4SAndroid Build Coastguard Worker             attr: KVM_DEV_RISCV_AIA_ADDR_APLIC,
170*bb4ee6a4SAndroid Build Coastguard Worker             addr: raw_aplic_addr as u64,
171*bb4ee6a4SAndroid Build Coastguard Worker             flags: 0,
172*bb4ee6a4SAndroid Build Coastguard Worker         };
173*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we allocated the struct that's being passed in, and raw_aplic_addr is
174*bb4ee6a4SAndroid Build Coastguard Worker         // pointing to a uniquely owned local, mutable variable.
175*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR, &kvm_attr) };
176*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
177*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
178*bb4ee6a4SAndroid Build Coastguard Worker         }
179*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..num_vcpus {
180*bb4ee6a4SAndroid Build Coastguard Worker             let imsic_addr = aia_imsic_addr(i);
181*bb4ee6a4SAndroid Build Coastguard Worker             let raw_imsic_addr = &imsic_addr as *const u64;
182*bb4ee6a4SAndroid Build Coastguard Worker             let kvm_attr = kvm_device_attr {
183*bb4ee6a4SAndroid Build Coastguard Worker                 group: KVM_DEV_RISCV_AIA_GRP_ADDR,
184*bb4ee6a4SAndroid Build Coastguard Worker                 attr: aia_addr_imsic(i as u64),
185*bb4ee6a4SAndroid Build Coastguard Worker                 addr: raw_imsic_addr as u64,
186*bb4ee6a4SAndroid Build Coastguard Worker                 flags: 0,
187*bb4ee6a4SAndroid Build Coastguard Worker             };
188*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we allocated the struct that's being passed in, and raw_imsic_addr is
189*bb4ee6a4SAndroid Build Coastguard Worker             // pointing to a uniquely owned local, mutable variable.
190*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR, &kvm_attr) };
191*bb4ee6a4SAndroid Build Coastguard Worker             if ret != 0 {
192*bb4ee6a4SAndroid Build Coastguard Worker                 return errno_result();
193*bb4ee6a4SAndroid Build Coastguard Worker             }
194*bb4ee6a4SAndroid Build Coastguard Worker         }
195*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
196*bb4ee6a4SAndroid Build Coastguard Worker     }
197*bb4ee6a4SAndroid Build Coastguard Worker }
198*bb4ee6a4SAndroid Build Coastguard Worker 
199*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for AiaDescriptor {
as_raw_descriptor(&self) -> RawDescriptor200*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
201*bb4ee6a4SAndroid Build Coastguard Worker         self.0.as_raw_descriptor()
202*bb4ee6a4SAndroid Build Coastguard Worker     }
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker 
205*bb4ee6a4SAndroid Build Coastguard Worker /// IrqChip implementation where the entire IrqChip is emulated by KVM.
206*bb4ee6a4SAndroid Build Coastguard Worker ///
207*bb4ee6a4SAndroid Build Coastguard Worker /// This implementation will use the KVM API to create and configure the in-kernel irqchip.
208*bb4ee6a4SAndroid Build Coastguard Worker pub struct KvmKernelIrqChip {
209*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) vm: KvmVm,
210*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
211*bb4ee6a4SAndroid Build Coastguard Worker     num_vcpus: usize,
212*bb4ee6a4SAndroid Build Coastguard Worker     num_ids: usize,     // number of imsics ids
213*bb4ee6a4SAndroid Build Coastguard Worker     num_sources: usize, // number of aplic sources
214*bb4ee6a4SAndroid Build Coastguard Worker     aia: AiaDescriptor,
215*bb4ee6a4SAndroid Build Coastguard Worker     device_kind: DeviceKind,
216*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) routes: Arc<Mutex<Vec<IrqRoute>>>,
217*bb4ee6a4SAndroid Build Coastguard Worker }
218*bb4ee6a4SAndroid Build Coastguard Worker 
219*bb4ee6a4SAndroid Build Coastguard Worker impl KvmKernelIrqChip {
220*bb4ee6a4SAndroid Build Coastguard Worker     /// Construct a new KvmKernelIrqchip.
new(vm: KvmVm, num_vcpus: usize) -> Result<KvmKernelIrqChip>221*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(vm: KvmVm, num_vcpus: usize) -> Result<KvmKernelIrqChip> {
222*bb4ee6a4SAndroid Build Coastguard Worker         let aia = AiaDescriptor(vm.create_device(DeviceKind::RiscvAia)?);
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker         let aia_mode = aia.get_aia_mode()?;
225*bb4ee6a4SAndroid Build Coastguard Worker         // Only support full emulation in the kernel.
226*bb4ee6a4SAndroid Build Coastguard Worker         if aia_mode != AIA_MODE_HWACCEL && aia_mode != AIA_MODE_AUTO {
227*bb4ee6a4SAndroid Build Coastguard Worker             return Err(BaseError::new(libc::ENOTSUP));
228*bb4ee6a4SAndroid Build Coastguard Worker         }
229*bb4ee6a4SAndroid Build Coastguard Worker 
230*bb4ee6a4SAndroid Build Coastguard Worker         // Don't need any wired interrupts, riscv can run PCI/MSI(X) only.
231*bb4ee6a4SAndroid Build Coastguard Worker         const NUM_SOURCES: u32 = 0;
232*bb4ee6a4SAndroid Build Coastguard Worker         aia.set_num_sources(NUM_SOURCES)?;
233*bb4ee6a4SAndroid Build Coastguard Worker 
234*bb4ee6a4SAndroid Build Coastguard Worker         let num_ids = aia.get_num_ids()?;
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker         // set the number of bits needed for this count of harts.
237*bb4ee6a4SAndroid Build Coastguard Worker         // Need at least one bit.
238*bb4ee6a4SAndroid Build Coastguard Worker         let max_hart_idx = num_vcpus as u64 - 1;
239*bb4ee6a4SAndroid Build Coastguard Worker         let num_hart_bits = std::cmp::max(1, 64 - max_hart_idx.leading_zeros());
240*bb4ee6a4SAndroid Build Coastguard Worker         aia.set_hart_bits(num_hart_bits)?;
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker         Ok(KvmKernelIrqChip {
243*bb4ee6a4SAndroid Build Coastguard Worker             vm,
244*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: Arc::new(Mutex::new((0..num_vcpus).map(|_| None).collect())),
245*bb4ee6a4SAndroid Build Coastguard Worker             num_vcpus,
246*bb4ee6a4SAndroid Build Coastguard Worker             num_ids: num_ids as usize,
247*bb4ee6a4SAndroid Build Coastguard Worker             num_sources: NUM_SOURCES as usize,
248*bb4ee6a4SAndroid Build Coastguard Worker             aia,
249*bb4ee6a4SAndroid Build Coastguard Worker             device_kind: DeviceKind::RiscvAia,
250*bb4ee6a4SAndroid Build Coastguard Worker             routes: Arc::new(Mutex::new(kvm_default_irq_routing_table(
251*bb4ee6a4SAndroid Build Coastguard Worker                 NUM_SOURCES as usize,
252*bb4ee6a4SAndroid Build Coastguard Worker             ))),
253*bb4ee6a4SAndroid Build Coastguard Worker         })
254*bb4ee6a4SAndroid Build Coastguard Worker     }
255*bb4ee6a4SAndroid Build Coastguard Worker 
256*bb4ee6a4SAndroid Build Coastguard Worker     /// Attempt to create a shallow clone of this riscv64 KvmKernelIrqChip instance.
257*bb4ee6a4SAndroid Build Coastguard Worker     /// This is the arch-specific impl used by `KvmKernelIrqChip::clone()`.
arch_try_clone(&self) -> Result<Self>258*bb4ee6a4SAndroid Build Coastguard Worker     pub(super) fn arch_try_clone(&self) -> Result<Self> {
259*bb4ee6a4SAndroid Build Coastguard Worker         Ok(KvmKernelIrqChip {
260*bb4ee6a4SAndroid Build Coastguard Worker             vm: self.vm.try_clone()?,
261*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: self.vcpus.clone(),
262*bb4ee6a4SAndroid Build Coastguard Worker             num_vcpus: self.num_vcpus,
263*bb4ee6a4SAndroid Build Coastguard Worker             num_ids: self.num_ids,
264*bb4ee6a4SAndroid Build Coastguard Worker             num_sources: self.num_sources,
265*bb4ee6a4SAndroid Build Coastguard Worker             aia: self.aia.try_clone()?,
266*bb4ee6a4SAndroid Build Coastguard Worker             device_kind: self.device_kind,
267*bb4ee6a4SAndroid Build Coastguard Worker             routes: self.routes.clone(),
268*bb4ee6a4SAndroid Build Coastguard Worker         })
269*bb4ee6a4SAndroid Build Coastguard Worker     }
270*bb4ee6a4SAndroid Build Coastguard Worker }
271*bb4ee6a4SAndroid Build Coastguard Worker 
272*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChipRiscv64 for KvmKernelIrqChip {
try_box_clone(&self) -> Result<Box<dyn IrqChipRiscv64>>273*bb4ee6a4SAndroid Build Coastguard Worker     fn try_box_clone(&self) -> Result<Box<dyn IrqChipRiscv64>> {
274*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(self.try_clone()?))
275*bb4ee6a4SAndroid Build Coastguard Worker     }
276*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip(&self) -> &dyn IrqChip277*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip(&self) -> &dyn IrqChip {
278*bb4ee6a4SAndroid Build Coastguard Worker         self
279*bb4ee6a4SAndroid Build Coastguard Worker     }
280*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip_mut(&mut self) -> &mut dyn IrqChip281*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
282*bb4ee6a4SAndroid Build Coastguard Worker         self
283*bb4ee6a4SAndroid Build Coastguard Worker     }
284*bb4ee6a4SAndroid Build Coastguard Worker 
finalize(&self) -> Result<()>285*bb4ee6a4SAndroid Build Coastguard Worker     fn finalize(&self) -> Result<()> {
286*bb4ee6a4SAndroid Build Coastguard Worker         // The kernel needs the number of vcpus finalized before setting up the address for each
287*bb4ee6a4SAndroid Build Coastguard Worker         // interrupt controller.
288*bb4ee6a4SAndroid Build Coastguard Worker         self.aia.set_aplic_addrs(self.num_vcpus)?;
289*bb4ee6a4SAndroid Build Coastguard Worker         self.aia.aia_init()?;
290*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
291*bb4ee6a4SAndroid Build Coastguard Worker     }
292*bb4ee6a4SAndroid Build Coastguard Worker 
get_num_ids_sources(&self) -> (usize, usize)293*bb4ee6a4SAndroid Build Coastguard Worker     fn get_num_ids_sources(&self) -> (usize, usize) {
294*bb4ee6a4SAndroid Build Coastguard Worker         (self.num_ids, self.num_sources)
295*bb4ee6a4SAndroid Build Coastguard Worker     }
296*bb4ee6a4SAndroid Build Coastguard Worker }
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker /// Default RiscV routing table.
kvm_default_irq_routing_table(num_sources: usize) -> Vec<IrqRoute>299*bb4ee6a4SAndroid Build Coastguard Worker fn kvm_default_irq_routing_table(num_sources: usize) -> Vec<IrqRoute> {
300*bb4ee6a4SAndroid Build Coastguard Worker     let mut routes: Vec<IrqRoute> = Vec::new();
301*bb4ee6a4SAndroid Build Coastguard Worker 
302*bb4ee6a4SAndroid Build Coastguard Worker     for i in 0..num_sources {
303*bb4ee6a4SAndroid Build Coastguard Worker         routes.push(IrqRoute::aia_irq_route(i as u32));
304*bb4ee6a4SAndroid Build Coastguard Worker     }
305*bb4ee6a4SAndroid Build Coastguard Worker 
306*bb4ee6a4SAndroid Build Coastguard Worker     routes
307*bb4ee6a4SAndroid Build Coastguard Worker }
308