Skip to content

Commit ee93eff

Browse files
committed
UefiCpuPkg: Enable the IPI vectors on LoongArch
Since the LoongArch AP boot spec is published, it can identify which IPI by vector. Added IPI vector logic and enabled them. Signed-off-by: Chao Li <lichao@loongson.cn> Cc: Ray Ni <ray.ni@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Zhiguang Liu <zhiguang.liu@intel.com> Cc: Dun Tan <dun.tan@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Dongyan Qian <qiandongyan@loongson.cn> Cc: Xiangdong Meng <mengxiangdong@loongson.cn>
1 parent a179333 commit ee93eff

File tree

4 files changed

+84
-80
lines changed

4 files changed

+84
-80
lines changed

UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionCommon.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
#ifndef EXCEPTION_COMMON_H_
1111
#define EXCEPTION_COMMON_H_
1212

13+
#include <Base.h>
14+
1315
#define MAX_DEBUG_MESSAGE_LENGTH 0x100
16+
#define SMP_BOOT_CPU BIT0
17+
#define SMP_RESCHEDULE BIT1
18+
#define SMP_CALL_FUNCTION BIT2
1419

1520
extern INTN mExceptionKnownNameNum;
1621
extern INTN mInterruptKnownNameNum;

UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/ArchExceptionHandler.c

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ DumpImageAndCpuContent (
226226
/**
227227
IPI Interrupt Handler.
228228
229+
Generally, the IPI interrupt uses three vector:
230+
SMP_BOOT_CPU BSP boots AP. The BSP may reside in OS or other non-UEFI environment.
231+
SMP_RESCHEDULE BSP calls AP via UEFI MpInitLib.
232+
SMP_CALL_FUNCTION BSP calls AP to jump specified pointer, which allows with one parameter.
233+
229234
@param InterruptType The type of interrupt that occurred
230235
@param SystemContext A pointer to the system context when the interrupt occurred
231236
**/
@@ -236,43 +241,74 @@ IpiInterruptHandler (
236241
IN EFI_SYSTEM_CONTEXT SystemContext
237242
)
238243
{
239-
UINTN ResumeVector;
240-
UINTN Parameter;
244+
UINTN ResumeVector = 0;
245+
UINTN Parameter = 0;
246+
UINTN IpiStatus = 0;
247+
248+
IpiStatus = IoCsrRead32 (LOONGARCH_IOCSR_IPI_STATUS);
241249

242250
//
243251
// Clear interrupt.
244252
//
245-
IoCsrWrite32 (LOONGARCH_IOCSR_IPI_CLEAR, IoCsrRead32 (LOONGARCH_IOCSR_IPI_STATUS));
253+
IoCsrWrite32 (LOONGARCH_IOCSR_IPI_CLEAR, IpiStatus);
246254

247-
//
248-
// Get the resume vector and parameter if populated.
249-
//
250-
ResumeVector = IoCsrRead64 (LOONGARCH_IOCSR_MBUF0);
251-
Parameter = IoCsrRead64 (LOONGARCH_IOCSR_MBUF3);
255+
if ((IpiStatus & SMP_RESCHEDULE) != 0) {
256+
MemoryFence ();
257+
return;
258+
} else {
259+
if (((IpiStatus & SMP_BOOT_CPU) != 0) || ((IpiStatus & SMP_CALL_FUNCTION) != 0)) {
260+
//
261+
// Confirm that the mail box message has arrived.
262+
//
263+
do {
264+
ResumeVector = IoCsrRead32 (LOONGARCH_IOCSR_MBUF0);
265+
} while (!ResumeVector);
252266

253-
//
254-
// Clean up current processor mailbox 0 and mailbox 3.
255-
//
256-
IoCsrWrite64 (LOONGARCH_IOCSR_MBUF0, 0x0);
257-
IoCsrWrite64 (LOONGARCH_IOCSR_MBUF3, 0x0);
267+
//
268+
// Get the resume vector if populated.
269+
//
270+
ResumeVector = IoCsrRead64 (LOONGARCH_IOCSR_MBUF0);
271+
272+
if ((IpiStatus & SMP_BOOT_CPU) != 0) {
273+
SystemContext.SystemContextLoongArch64->PRMD &= ~((UINT64)BIT2); // Clean PIE
274+
} else if ((IpiStatus & SMP_CALL_FUNCTION) != 0) {
275+
//
276+
// Confirm that the mail box message has arrived.
277+
//
278+
do {
279+
Parameter = IoCsrRead32 (LOONGARCH_IOCSR_MBUF3);
280+
} while (!Parameter);
281+
282+
//
283+
// Get the parameter if populated.
284+
//
285+
Parameter = IoCsrRead64 (LOONGARCH_IOCSR_MBUF3);
286+
287+
//
288+
// Set $a0 as APIC ID and $a1 as parameter value.
289+
//
290+
SystemContext.SystemContextLoongArch64->R4 = (CsrRead (LOONGARCH_CSR_CPUID) & 0x1FF);
291+
SystemContext.SystemContextLoongArch64->R5 = Parameter;
292+
}
293+
} else {
294+
InternalPrintMessage (
295+
"Core %d: Should never be here, IPI Status = %d.\n",
296+
CsrRead (LOONGARCH_CSR_CPUID),
297+
IpiStatus
298+
);
299+
DefaultExceptionHandler (EXCEPT_LOONGARCH_INT, SystemContext);
300+
}
258301

259-
//
260-
// If mailbox 0 is non-NULL, it means that the BSP or other cores called the IPI to wake
261-
// up the current core and let it use the resume vector stored in mailbox 0.
262-
//
263-
// If both the resume vector and parameter are non-NULL, it means that the IPI was
264-
// called in the BIOS.
265-
//
266-
// The situation where the resume vector is non-NULL and the parameter is NULL has been
267-
// processed after the exception entry is pushed onto the stack.
268-
//
269-
if ((ResumeVector != 0) && (Parameter != 0)) {
270-
SystemContext.SystemContextLoongArch64->ERA = ResumeVector;
271302
//
272-
// Set $a0 as APIC ID and $a1 as parameter value.
303+
// Clean up current processor mailbox 0 and mailbox 3.
304+
//
305+
IoCsrWrite64 (LOONGARCH_IOCSR_MBUF0, 0x0);
306+
IoCsrWrite64 (LOONGARCH_IOCSR_MBUF3, 0x0);
307+
273308
//
274-
SystemContext.SystemContextLoongArch64->R4 = CsrRead (LOONGARCH_CSR_CPUID);
275-
SystemContext.SystemContextLoongArch64->R5 = Parameter;
309+
// Set the ERA to the resume vector sent by caller.
310+
//
311+
SystemContext.SystemContextLoongArch64->ERA = ResumeVector;
276312
}
277313

278314
MemoryFence ();

UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/ExceptionHandlerAsm.S

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ ASM_PFX(ExceptionEntryStart):
250250

251251
csrrd $t0, LOONGARCH_CSR_EUEN
252252
andi $t0, $t0, CSR_EUEN_FPEN
253-
beqz $t0, PushRegDone
253+
beqz $t0, EntryConmmonHanlder
254254

255255
fst.d $fa0, $sp, 0 * RSIZE
256256
fst.d $fa1, $sp, 1 * RSIZE
@@ -312,52 +312,6 @@ ASM_PFX(ExceptionEntryStart):
312312
// Push exception context down
313313
//
314314

315-
PushRegDone:
316-
//
317-
// Process IPI only when mailbox3 is NULL and mailbox0 is no-NULL.
318-
//
319-
li.d $t0, LOONGARCH_IOCSR_MBUF0
320-
iocsrrd.d $a0, $t0
321-
beqz $a0, EntryConmmonHanlder
322-
323-
li.d $t0, LOONGARCH_IOCSR_MBUF3
324-
iocsrrd.d $t1, $t0
325-
bnez $t1, EntryConmmonHanlder
326-
327-
csrrd $t0, LOONGARCH_CSR_ESTAT
328-
srli.d $t0, $t0, 12
329-
andi $t0, $t0, 0x1
330-
beqz $t0, EntryConmmonHanlder
331-
332-
//
333-
// Clean up current processor mailbox 0 and mailbox 3.
334-
//
335-
li.d $t0, LOONGARCH_IOCSR_MBUF0
336-
iocsrwr.d $zero, $t0
337-
li.d $t0, LOONGARCH_IOCSR_MBUF3
338-
iocsrwr.d $zero, $t0
339-
340-
//
341-
// Clear IPI interrupt.
342-
//
343-
li.d $t0, LOONGARCH_IOCSR_IPI_STATUS
344-
iocsrrd.w $t1, $t0
345-
li.d $t0, LOONGARCH_IOCSR_IPI_CLEAR
346-
iocsrwr.w $t1, $t0
347-
348-
//
349-
// Only kernel stage BSP calls IPI without parameters. Clean up the PIE and make sure
350-
// global interrupts are turned off for the current processor when jumping to the kernel.
351-
//
352-
csrwr $a0, LOONGARCH_CSR_ERA // Update ERA
353-
li.w $t0, BIT2 // IE
354-
csrxchg $zero, $t0, LOONGARCH_CSR_PRMD // Clean PIE
355-
356-
//
357-
// Return this exception and jump to kernel using ERA.
358-
//
359-
ertn
360-
361315
EntryConmmonHanlder:
362316
addi.d $sp, $sp, -(GP_REG_CONTEXT_SIZE + CSR_REG_CONTEXT_SIZE)
363317
move $a0, $sp

UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,12 @@ WakeUpAP (
727727
LOONGARCH_IOCSR_IPI_SEND,
728728
(IOCSR_MBUF_SEND_BLOCKING |
729729
(mProcessorResourceData->ApicId[Index] << IOCSR_MBUF_SEND_CPU_SHIFT) |
730-
0x2 // Bit 2
730+
0x2 // SMP_CALL_FUNCTION
731731
)
732732
);
733+
734+
MemoryFence ();
735+
MicroSecondDelay (100); // Delay 100ms after send IPI.
733736
}
734737
}
735738
} else {
@@ -757,15 +760,18 @@ WakeUpAP (
757760
*(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
758761

759762
//
760-
// Send IPI 4 interrupt to wake up APs.
763+
// Send IPI 2 interrupt to wake up APs.
761764
//
762765
IoCsrWrite64 (
763766
LOONGARCH_IOCSR_IPI_SEND,
764767
(IOCSR_MBUF_SEND_BLOCKING |
765768
(CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
766-
0x2 // Bit 2
769+
0x1 // SMP_RESCHEDULE
767770
)
768771
);
772+
773+
MemoryFence ();
774+
MicroSecondDelay (100); // Delay 100ms after send IPI.
769775
}
770776
}
771777

@@ -789,16 +795,19 @@ WakeUpAP (
789795
*(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
790796

791797
//
792-
// Send IPI 4 interrupt to wake up APs.
798+
// Send IPI 2 interrupt to wake up APs.
793799
//
794800
IoCsrWrite64 (
795801
LOONGARCH_IOCSR_IPI_SEND,
796802
(IOCSR_MBUF_SEND_BLOCKING |
797803
(CpuInfoInHob[ProcessorNumber].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
798-
0x2 // Bit 2
804+
0x1 // SMP_RESCHEDULE
799805
)
800806
);
801807

808+
MemoryFence ();
809+
MicroSecondDelay (100); // Delay 100ms after send IPI.
810+
802811
//
803812
// Wait specified AP waken up
804813
//

0 commit comments

Comments
 (0)