mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 12:16:48 +00:00
128 lines
3.6 KiB
Rust
128 lines
3.6 KiB
Rust
use crate::exception::ipi::{IpiKind, IpiTarget};
|
|
|
|
extern "C" {
|
|
pub fn apic_write_icr(value: u64);
|
|
pub fn apic_x2apic_enabled() -> bool;
|
|
}
|
|
|
|
/// IPI的种类(架构相关,指定了向量号)
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
|
#[repr(u8)]
|
|
pub enum ArchIpiKind {
|
|
KickCpu = 200,
|
|
FlushTLB = 201,
|
|
}
|
|
|
|
impl From<IpiKind> for ArchIpiKind {
|
|
fn from(kind: IpiKind) -> Self {
|
|
match kind {
|
|
IpiKind::KickCpu => ArchIpiKind::KickCpu,
|
|
IpiKind::FlushTLB => ArchIpiKind::FlushTLB,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// IPI投递目标
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
|
pub enum ArchIpiTarget {
|
|
/// 当前CPU
|
|
Current,
|
|
/// 所有CPU
|
|
All,
|
|
/// 除了当前CPU以外的所有CPU
|
|
Other,
|
|
/// 指定的CPU
|
|
Specified(usize),
|
|
}
|
|
|
|
impl From<IpiTarget> for ArchIpiTarget {
|
|
fn from(target: IpiTarget) -> Self {
|
|
match target {
|
|
IpiTarget::Current => ArchIpiTarget::Current,
|
|
IpiTarget::All => ArchIpiTarget::All,
|
|
IpiTarget::Other => ArchIpiTarget::Other,
|
|
IpiTarget::Specified(cpu_id) => ArchIpiTarget::Specified(cpu_id),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ArchIpiTarget {
|
|
pub fn shorthand(&self) -> u8 {
|
|
match self {
|
|
ArchIpiTarget::Specified(_) => 0,
|
|
ArchIpiTarget::Current => 1,
|
|
ArchIpiTarget::All => 2,
|
|
ArchIpiTarget::Other => 3,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Into<x86::apic::DestinationShorthand> for ArchIpiTarget {
|
|
fn into(self) -> x86::apic::DestinationShorthand {
|
|
match self {
|
|
ArchIpiTarget::Specified(_) => x86::apic::DestinationShorthand::NoShorthand,
|
|
ArchIpiTarget::Current => x86::apic::DestinationShorthand::Myself,
|
|
ArchIpiTarget::All => x86::apic::DestinationShorthand::AllIncludingSelf,
|
|
ArchIpiTarget::Other => x86::apic::DestinationShorthand::AllExcludingSelf,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Into<x86::apic::ApicId> for ArchIpiTarget {
|
|
fn into(self) -> x86::apic::ApicId {
|
|
let id = match self {
|
|
ArchIpiTarget::Specified(cpu_id) => cpu_id,
|
|
_ => 0,
|
|
};
|
|
|
|
if unsafe { apic_x2apic_enabled() } {
|
|
return x86::apic::ApicId::X2Apic(id as u32);
|
|
} else {
|
|
return x86::apic::ApicId::XApic(id as u8);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn send_ipi(kind: IpiKind, target: IpiTarget) {
|
|
// kdebug!("send_ipi: {:?} {:?}", kind, target);
|
|
|
|
let ipi_vec = ArchIpiKind::from(kind) as u8;
|
|
let target = ArchIpiTarget::from(target);
|
|
let shorthand: x86::apic::DestinationShorthand = target.into();
|
|
let destination: x86::apic::ApicId = target.into();
|
|
if unsafe { apic_x2apic_enabled() } {
|
|
// kdebug!("send_ipi: x2apic");
|
|
let icr = x86::apic::Icr::for_x2apic(
|
|
ipi_vec,
|
|
destination,
|
|
shorthand,
|
|
x86::apic::DeliveryMode::Fixed,
|
|
x86::apic::DestinationMode::Physical,
|
|
x86::apic::DeliveryStatus::Idle,
|
|
x86::apic::Level::Assert,
|
|
x86::apic::TriggerMode::Edge,
|
|
);
|
|
|
|
unsafe {
|
|
apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64);
|
|
}
|
|
} else {
|
|
// kdebug!("send_ipi: xapic");
|
|
let icr = x86::apic::Icr::for_xapic(
|
|
ipi_vec,
|
|
destination,
|
|
shorthand,
|
|
x86::apic::DeliveryMode::Fixed,
|
|
x86::apic::DestinationMode::Physical,
|
|
x86::apic::DeliveryStatus::Idle,
|
|
x86::apic::Level::Assert,
|
|
x86::apic::TriggerMode::Edge,
|
|
);
|
|
|
|
unsafe {
|
|
apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64);
|
|
}
|
|
}
|
|
}
|