From 1bebf4d37b9e49eb57229371afb8b626ef93c1e8 Mon Sep 17 00:00:00 2001 From: "Chloe M." Date: Fri, 26 Jun 2026 22:47:01 +0000 Subject: [PATCH] stos/amd64: lapic: Add support for IPIs Signed-off-by: Chloe M. --- paw/stos/arch/amd64/cpu/lapic.c | 58 +++++++++++++++++++++++++++++ paw/stos/head/arch/amd64/lapic.h | 17 ++++++++- paw/stos/head/arch/amd64/lapicreg.h | 3 ++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/paw/stos/arch/amd64/cpu/lapic.c b/paw/stos/arch/amd64/cpu/lapic.c index 2c7a2eb..72de310 100644 --- a/paw/stos/arch/amd64/cpu/lapic.c +++ b/paw/stos/arch/amd64/cpu/lapic.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -135,9 +136,66 @@ LapicEnable(MCB *Mcb) DTRACE_BSP("enabled %s %s\n", type, mode); } +VOID +MdLapicSendIpi(UCHAR Vector, UCHAR DestId, BOOLEAN LogicalDest, + IPI_SHORTHAND Xnd, IPI_DELMOD DelMod) +{ + KPCR *ThisCore; + MCB *Mcb; + ULONG IcrLow, IcrHigh; + ULONG Icr = 0; + + /* + * If the shorthand is refering to ourselves and we are x2APIC we + * can use a better path via its specialized SELF IPI MSR. + */ + ThisCore = HalKpcrCurrent(); + if (Xnd == IPI_XND_SELF && Mcb->HasX2Apic) { + MdWrmsr(LAPIC_SELF_IPI, Vector); + return; + } + + Mcb = &ThisCore->Mcb; + + /* Clamp these fields */ + DelMod &= 7; + Xnd &= 3; + + /* Encode the ICR */ + Icr |= Vector & 0xFF; + Icr |= Xnd << 18; + Icr |= DelMod << 8; + Icr |= LogicalDest << 11; + + /* For xAPIC only */ + if (!Mcb->HasX2Apic) { + IcrHigh = ((UQUAD)Icr >> 32) & (ULONG)-1; + IcrLow = Icr & (ULONG)-1; + IcrHigh |= (UQUAD)DestId << 24; + + LapicRegWrite(Mcb, LAPIC_ICRHI, IcrHigh); + LapicRegWrite(Mcb, LAPIC_ICRLO, IcrLow); + + /* Only on legacy xAPICs do we poll */ + for (;;) { + Icr = LapicRegRead(Mcb, LAPIC_ICRLO); + if (ISSET(Icr, IPI_DELSTAT_PENDING)) + HalCpuSpinWait(); + } + + return; + } + + /* On x2APICs only as it queues */ + Icr |= (UQUAD)DestId << 32; + LapicRegWrite(Mcb, LAPIC_ICRLO, Icr); +} + VOID MdLapicInit(KPCR *Kpcr) { + INTR_HANDLER Handler; + INTR_DATA *IntrData; ACPI_MADT *Madt; MCB *Mcb; diff --git a/paw/stos/head/arch/amd64/lapic.h b/paw/stos/head/arch/amd64/lapic.h index 54dc366..9f1aca7 100644 --- a/paw/stos/head/arch/amd64/lapic.h +++ b/paw/stos/head/arch/amd64/lapic.h @@ -51,7 +51,7 @@ typedef enum { } IPI_DELMOD; /* IPI Delivery status bits */ -#define IPI_DELSTAT_PENDING BIT(0) +#define IPI_DELSTAT_PENDING BIT(12) /* IPI Destination mode */ #define IPI_DELMOD_LOGICAL BIT(0) @@ -64,4 +64,19 @@ typedef enum { */ VOID MdLapicInit(KPCR *Kpcr); +/* + * Send an inter-processor interrupt + * + * @Vector: Interrupt vector to assign to ICR + * @DestId: Target APIC ID [depends on @LogicalDest] + * @LogicalDest: If true, IPI destination is logical + * @Xnd: Destination shorthand + * @Delmod: Delivery mode + */ +VOID MdLapicSendIpi( + UCHAR Vector, UCHAR DestId, + BOOLEAN LogicalDest, IPI_SHORTHAND Xnd, + IPI_DELMOD DelMod +); + #endif /* !_MACHINE_LAPIC_H_ */ diff --git a/paw/stos/head/arch/amd64/lapicreg.h b/paw/stos/head/arch/amd64/lapicreg.h index e605163..2a6a1e9 100644 --- a/paw/stos/head/arch/amd64/lapicreg.h +++ b/paw/stos/head/arch/amd64/lapicreg.h @@ -61,4 +61,7 @@ #define LVT_TMR_PERIODIC 0x01 #define LVT_TMR_TSC_DEADLINE 0x02 +/* MSR for x2APICs only */ +#define LAPIC_SELF_IPI 0x083F + #endif /* !_MACHINE_LAPICREG_H_ */