From 0b4ff68b81ab284979592f94ad5a98b3fc88dcdb Mon Sep 17 00:00:00 2001 From: Jon Lange Date: Thu, 23 Jan 2025 13:29:59 -0800 Subject: [PATCH] platform: implement `SvsmPlatform::is_external_interrupt` for TDP. The TDP platform must use APIC virtualization to check whether a given interrupt event originates from a hardware interrupt or a software interrupt. This change implements the logic to read the required state from the APIC. Signed-off-by: Jon Lange --- kernel/src/cpu/x86/apic.rs | 16 ++++++++++++++++ kernel/src/cpu/x86/mod.rs | 1 + kernel/src/platform/native.rs | 4 +--- kernel/src/platform/tdp.rs | 8 +++++--- 4 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 kernel/src/cpu/x86/apic.rs diff --git a/kernel/src/cpu/x86/apic.rs b/kernel/src/cpu/x86/apic.rs new file mode 100644 index 000000000..92128db37 --- /dev/null +++ b/kernel/src/cpu/x86/apic.rs @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) Microsoft Corporation +// +// Author: Jon Lange + +pub const APIC_MSR_EOI: u32 = 0x80B; +pub const APIC_MSR_ISR: u32 = 0x810; +pub const APIC_MSR_ICR: u32 = 0x830; + +// Returns the MSR offset and bitmask to identify a specific vector in an +// APIC register (IRR, ISR, or TMR). +pub fn apic_register_bit(vector: usize) -> (u32, u32) { + let index: u8 = vector as u8; + ((index >> 5) as u32, 1 << (index & 0x1F)) +} diff --git a/kernel/src/cpu/x86/mod.rs b/kernel/src/cpu/x86/mod.rs index 7f7ba665a..d888b5830 100644 --- a/kernel/src/cpu/x86/mod.rs +++ b/kernel/src/cpu/x86/mod.rs @@ -4,4 +4,5 @@ // // Authors: Thomas Leroy +pub mod apic; pub mod smap; diff --git a/kernel/src/platform/native.rs b/kernel/src/platform/native.rs index 003196a76..99125ee38 100644 --- a/kernel/src/platform/native.rs +++ b/kernel/src/platform/native.rs @@ -12,6 +12,7 @@ use crate::cpu::cpuid::CpuidResult; use crate::cpu::msr::{read_msr, write_msr}; use crate::cpu::percpu::PerCpu; use crate::cpu::smp::create_ap_start_context; +use crate::cpu::x86::apic::{APIC_MSR_EOI, APIC_MSR_ICR}; use crate::error::SvsmError; use crate::hyperv; use crate::hyperv::{hyperv_setup_hypercalls, hyperv_start_cpu, is_hyperv_hypervisor}; @@ -33,9 +34,6 @@ use bootlib::platform::SvsmPlatformType; const MSR_APIC_BASE: u32 = 0x1B; const APIC_X2_ENABLE_MASK: u64 = 0xC00; -const APIC_MSR_EOI: u32 = 0x80B; -const APIC_MSR_ICR: u32 = 0x830; - #[derive(Clone, Copy, Debug)] pub struct NativePlatform { is_hyperv: bool, diff --git a/kernel/src/platform/tdp.rs b/kernel/src/platform/tdp.rs index c14710762..e4d428aff 100644 --- a/kernel/src/platform/tdp.rs +++ b/kernel/src/platform/tdp.rs @@ -7,7 +7,9 @@ use crate::address::{Address, PhysAddr, VirtAddr}; use crate::console::init_svsm_console; use crate::cpu::cpuid::CpuidResult; +use crate::cpu::msr::read_msr; use crate::cpu::percpu::PerCpu; +use crate::cpu::x86::apic::{apic_register_bit, APIC_MSR_ISR}; use crate::error::SvsmError; use crate::hyperv; use crate::io::IOPort; @@ -171,11 +173,11 @@ impl SvsmPlatform for TdpPlatform { fn eoi(&self) {} - fn is_external_interrupt(&self, _vector: usize) -> bool { + fn is_external_interrupt(&self, vector: usize) -> bool { // Examine the APIC ISR to determine whether this interrupt vector is // active. If so, it is assumed to be an external interrupt. - // TODO - add code to read the APIC ISR. - todo!(); + let (msr, mask) = apic_register_bit(vector); + (read_msr(APIC_MSR_ISR + msr) & mask as u64) != 0 } fn start_cpu(