1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
#------------------------------------------------------------------------------
#
# Start for Loongson LoongArch processor
#
# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
# @par Glossary:
# - CSR - CPU Status Register
# - EBASE - Exception Base Address
#------------------------------------------------------------------------------
#ifndef __ASSEMBLY__
#define __ASSEMBLY__
#endif
#include <Library/BaseMemoryLib.h>
#include <Register/LoongArch64/Csr.h>
#include <Protocol/DebugSupport.h>
#define BOOTCORE_ID 0
//
// For coding convenience, define the maximum valid
// LoongArch exception.
// Since UEFI V2.11, it will be present in DebugSupport.h.
//
#define MAX_LOONGARCH_EXCEPTION 64
ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
ASM_PFX(_ModuleEntryPoint):
/* Disable global interrupt */
bl DisableInterrupts
/* Disable all local interrupt */
li.w $a0, 0x1FFF
bl DisableLocalInterrupts
/* Read physical cpu number id */
bl GetApicId
li.d $t0, BOOTCORE_ID //0
bne $a0, $t0, SlaveMain
/* Set BSP stack */
li.d $t0, FixedPcdGet64(PcdOvmfSecPeiTempRamBase) + FixedPcdGet32(PcdOvmfSecPeiTempRamSize) # stack base
move $sp, $t0
addi.d $sp, $sp, -0x8
/* Load the exception vector base address */
li.d $s0, FixedPcdGet64(PcdLoongArchExceptionVectorBaseAddress)
/* Construct SEC and PEI step exception environment */
la.pcrel $a1, ExceptionEntryStart
la.pcrel $t0, ExceptionEntryEnd
sub.d $a2, $t0, $a1
li.w $t0, (MAX_LOONGARCH_EXCEPTION + MAX_LOONGARCH_INTERRUPT) * 512
bgeu $a2, $t0, DeadLoop
move $a0, $s0
bl CopyMem
/* Configure BSP reset ebase */
move $a0, $s0
bl SetExceptionBaseAddress
CallEntry:
/* Call C function make sure parameter true */
li.d $a0, FixedPcdGet64(PcdOvmfFdBaseAddress) # FW base
addi.d $a1, $sp, 0x8
bl SecCoreStartupWithStack
# End of _ModuleEntryPoint
ASM_PFX(ClearMailBox):
/* Clear mailbox */
li.d $t1, LOONGARCH_IOCSR_MBUF3
iocsrwr.d $zero, $t1
li.d $t1, LOONGARCH_IOCSR_MBUF2
iocsrwr.d $zero, $t1
li.d $t1, LOONGARCH_IOCSR_MBUF1
iocsrwr.d $zero, $t1
li.d $t1, LOONGARCH_IOCSR_MBUF0
iocsrwr.d $zero, $t1
jirl $zero, $ra, 0
# End of ClearMailBox
ASM_PFX(EnableIPI):
/* Enable IPI interrupt */
li.w $t1, BIT12
csrxchg $t1, $t1, LOONGARCH_CSR_ECFG
li.w $t2, 0xFFFFFFFFU
li.d $t1, LOONGARCH_IOCSR_IPI_EN
iocsrwr.w $t2, $t1
jirl $zero, $ra, 0
# End of EeableIPI
#/**
# Get APIC ID for every CPU.
#
# @param NULL
# @return APICID
#
# UINTN
# EFI_API
# GetApicId (
# VOID
# )
#**/
ASM_PFX(GetApicId):
csrrd $a0, LOONGARCH_CSR_CPUNUM
andi $a0, $a0, 0x3ff
jirl $zero, $ra, 0
# End of GetApicId
ASM_PFX(ApInitStack):
li.d $t1, SIZE_1KB
csrrd $t0, LOONGARCH_CSR_TMID
mul.d $t1, $t0, $t1
li.d $t2, FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)
bgeu $t0, $t2, DeadLoop
li.d $t0, FixedPcdGet64(PcdOvmfSecPeiTempRamBase) + FixedPcdGet32(PcdOvmfSecPeiTempRamSize) - SIZE_64KB
sub.d $sp, $t0, $t1
addi.d $sp, $sp, -0x8
jirl $zero, $ra, 0
# End of ApInitStack
ASM_PFX(SlaveMain):
/* Set AP exception handle in flash */
la.pcrel $a0, ApException
bl SetExceptionBaseAddress
/* Clean up local mail box and open INT */
bl ClearMailBox
bl EnableIPI
bl EnableInterrupts
WaitForWake:
/* Wait for wakeup */
bl CpuSleep
b WaitForWake
# End of SlaveMain
.align 12
ASM_PFX(ApException):
csrrd $t0, LOONGARCH_CSR_ESTAT
srli.d $t0, $t0, 12
andi $t0, $t0, 0x1
beqz $t0, DeadLoop
li.d $t0, LOONGARCH_IOCSR_IPI_STATUS
iocsrrd.w $t1, $t0
li.d $t0, LOONGARCH_IOCSR_IPI_CLEAR
iocsrwr.w $t1, $t0
/* Read mail buf and jump to specified entry */
li.d $t1, LOONGARCH_IOCSR_MBUF0
iocsrrd.d $t0, $t1
beqz $t0, OutOfException
csrwr $t0, LOONGARCH_CSR_ERA
li.d $t0, LOONGARCH_IOCSR_MBUF3
iocsrrd.d $a1, $t0
bl ClearMailBox
beqz $a1, NoParameterCall
//
// If the parameters are not NULL, then calling happened in FW ENV.
// Set the EBASE to be the same as BSP.
//
li.d $a0, FixedPcdGet64(PcdLoongArchExceptionVectorBaseAddress)
bl SetExceptionBaseAddress
bl ApInitStack
bl GetApicId
b OutOfException
NoParameterCall:
li.w $t0, BIT2 // IE
csrxchg $zero, $t0, LOONGARCH_CSR_PRMD // Clean PIE
OutOfException:
ertn
# End of ApException
ASM_PFX(DeadLoop):
b DeadLoop
# End of DeadLoop
.end
|