From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.3723.1668159900055995557 for ; Fri, 11 Nov 2022 01:45:01 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lichao@loongson.cn) Received: from loongson.cn (unknown [10.40.24.149]) by gateway (Coremail) with SMTP id _____8BxHdmaGW5jTxYGAA--.18764S3; Fri, 11 Nov 2022 17:44:58 +0800 (CST) Received: from lichao-PC (unknown [10.40.24.149]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Bxj+CZGW5jDdMQAA--.45710S2; Fri, 11 Nov 2022 17:44:57 +0800 (CST) Date: Fri, 11 Nov 2022 17:44:57 +0800 From: "Chao Li" To: xianglai li Cc: "=?utf-8?Q?devel=40edk2.groups.io?=" , Bibo Mao , Leif Lindholm , Liming Gao , Michael D Kinney Message-ID: In-Reply-To: <6d676eba440751bc6ab0ad02668aacbfa43d78da.1668157715.git.lixianglai@loongson.cn> References: <6d676eba440751bc6ab0ad02668aacbfa43d78da.1668157715.git.lixianglai@loongson.cn> Subject: Re: [edk2-platforms][PATCH V5 08/15] Platform/Loongson: Add CPU DXE driver. X-Mailer: Mailspring MIME-Version: 1.0 X-CM-TRANSID: AQAAf8Bxj+CZGW5jDdMQAA--.45710S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQAHCGNs6eQZ0AAdsY X-Coremail-Antispam: 1Uk129KBjvAXoWDAFWxKr1kZw1xXFWkKryxuFg_yoWruw45Zo W5Za92yw47J348Ja97C3Z3G3yxXF18uFs5Jr40yFsYgF90gF15CFW0y3ZxGw1fJF45XrZr GFyxX3Z7GFZIqrn5n29KB7ZKAUJUUUUD529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ec02F40Eb7x2x7xS6r1j6r4UMc02F40EFcxC0VAKzVAqx4xG6I80ewAqx4xG64kEw2xG 04xIwI0_Xr0_WrUv73VFW2AGmfu7bjvjm3AaLaJ3UjIYCTnIWjp_UUUOf7kC6x804xWl14 x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWU JVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84ACjcxK6xIIjxv20xvE14 v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4j6F4UM28EF7xvwVC2z280aVAF wI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVWxJr0_GcWln4kS14v26r126r1DM2 AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx1l5I8CrVAYj202 j2C_Jr0_Gr1l5I8CrVACY4xI64kE6c02F40Ex7xfMc02F40Ew4AK048IF2xKxVW5JVWrJw Av7VC0I7IYx2IY67AKxVWUtVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JMx8GjcxK6IxK0xIIj40E5I8CrwCY1x0262kKe7AKxV WUAVWUtwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E 14v26r106r1rMI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW5JVW7JwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F 4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jY9a9U UUUU= Content-Type: multipart/alternative; boundary="636e1999_50b78e22_1e57b" --636e1999_50b78e22_1e57b Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Reviewed-by: Chao Li Thanks, Chao -------- On 11=E6=9C=88 11 2022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li wrote: > The driver produces E=46I=5FCPU=5FARCH=5FPROTOCOL, > > Initialize the exception entry address. > > > RE=46: https://bugzilla.tianocore.org/show=5Fbug.cgi=3Fid=3D4054 > > > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > --- > .../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c =7C 367 ++++++++++++++++++= > .../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h =7C 199 ++++++++++ > .../Drivers/CpuDxe/CpuDxe.inf =7C 59 +++ > .../Drivers/CpuDxe/LoongArch64/Exception.c =7C 335 ++++++++++++++++ > .../Drivers/CpuDxe/LoongArch64/=46pu.S =7C 97 +++++ > .../Drivers/CpuDxe/LoongArch64/LoongArch.S =7C 321 +++++++++++++++ > 6 files changed, 1378 insertions(+) > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Cp= uDxe.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Cp= uDxe.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Cp= uDxe.inf > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Lo= ongArch64/Exception.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Lo= ongArch64/=46pu.S > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Lo= ongArch64/LoongArch.S > > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c= b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c > new file mode 100644 > index 0000000000..23f824d82b > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c > =40=40 -0,0 +1,367 =40=40 > +/** =40file > + CPU DXE Module to produce CPU ARCH Protocol > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include =22CpuDxe.h=22 > + > +BOOLEAN mInterruptState =3D =46ALSE; > + > +/* > + This function flushes the range of addresses from Start to Start+Leng= th > + from the processor's data cache. If Start is not aligned to a cache l= ine > + boundary, then the bytes before Start to the preceding cache line bou= ndary > + are also flushed. If Start+Length is not aligned to a cache line boun= dary, > + then the bytes past Start+Length to the end of the next cache line bo= undary > + are also flushed. The =46lushType of EfiCpu=46lushTypeWriteBackInvali= date must be > + supported. If the data cache is fully coherent with all DMA operation= s, then > + this function can just return E=46I=5FSUCCESS. If the processor does = not support > + flushing a range of the data cache, then the entire data cache can be= flushed. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + =40param Start The beginning physical address to flush from the proce= ssor's data > + cache. > + =40param Length The number of bytes to flush from the processor's dat= a cache. This > + function may flush more bytes than Length specifies depending upon > + the granularity of the flush operation that the processor supports. > + =40param =46lushType Specifies the type of flush operation to perform= . > + > + =40retval E=46I=5FSUCCESS The address range from Start to Start+Lengt= h was flushed from > + the processor's data cache. > + =40retval E=46I=5FUNSUPPORTEDT The processor does not support the cac= he flush type specified > + by =46lushType. > + =40retval E=46I=5FDEVICE=5FERROR The address range from Start to Star= t+Length could not be flushed > + from the processor's data cache. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +Cpu=46lushCpuDataCache ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN E=46I=5FPHYSICAL=5FADDRESS Start, > + IN UINT64 Length, > + IN E=46I=5FCPU=5F=46LUSH=5FTYPE =46lushType > + ) > +=7B > + switch (=46lushType) =7B > + case EfiCpu=46lushTypeWriteBack: > + WriteBackDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Length); > + break; > + case EfiCpu=46lushTypeInvalidate: > + InvalidateDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Length); > + break; > + case EfiCpu=46lushTypeWriteBackInvalidate: > + WriteBackInvalidateDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Leng= th); > + break; > + default: > + return E=46I=5FINVALID=5FPARAMETER; > + =7D > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + This function enables interrupt processing by the processor. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + > + =40retval E=46I=5FSUCCESS Interrupts are enabled on the processor. > + =40retval E=46I=5FDEVICE=5FERROR Interrupts could not be enabled on t= he processor. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuEnableInterrupt ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This > + ) > +=7B > + EnableInterrupts (); > + > + mInterruptState =3D TRUE; > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + This function disables interrupt processing by the processor. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + > + =40retval E=46I=5FSUCCESS Interrupts are disabled on the processor. > + =40retval E=46I=5FDEVICE=5FERROR Interrupts could not be disabled on = the processor. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuDisableInterrupt ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This > + ) > +=7B > + DisableInterrupts (); > + > + mInterruptState =3D =46ALSE; > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + This function retrieves the processor's current interrupt state a ret= urns it in > + State. If interrupts are currently enabled, then TRUE is returned. If= interrupts > + are currently disabled, then =46ALSE is returned. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + =40param State A pointer to the processor's current interrupt state. = Set to TRUE if > + interrupts are enabled and =46ALSE if interrupts are disabled. > + > + =40retval E=46I=5FSUCCESS The processor's current interrupt state was= returned in State. > + =40retval E=46I=5FINVALID=5FPARAMETER State is NULL. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuGetInterruptState ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + OUT BOOLEAN *State > + ) > +=7B > + if (State =3D=3D NULL) =7B > + return E=46I=5FINVALID=5FPARAMETER; > + =7D > + > + *State =3D mInterruptState; > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + This function generates an INIT on the processor. If this function su= cceeds, then the > + processor will be reset, and control will not be returned to the call= er. If InitType is > + not supported by this processor, or the processor cannot programmatic= ally generate an > + INIT without help from external hardware, then E=46I=5FUNSUPPORTED is= returned. If an error > + occurs attempting to generate an INIT, then E=46I=5FDEVICE=5FERROR is= returned. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + =40param InitType The type of processor INIT to perform. > + > + =40retval E=46I=5FSUCCESS The processor INIT was performed. This retu= rn code should never be seen. > + =40retval E=46I=5FUNSUPPORTED The processor INIT operation specified = by InitType is not supported > + by this processor. > + =40retval E=46I=5FDEVICE=5FERROR The processor INIT failed. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuInit ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN E=46I=5FCPU=5FINIT=5FTYPE InitType > + ) > +=7B > + return E=46I=5FUNSUPPORTED; > +=7D > + > +/** > + This function registers and enables the handler specified by Interrup= tHandler for a processor > + interrupt or exception type specified by InterruptType. If InterruptH= andler is NULL, then the > + handler for the processor interrupt or exception type specified by In= terruptType is uninstalled. > + The installed handler is called once for each processor interrupt or = exception. > + > + =40param InterruptType Interrupt Type. > + =40param InterruptHandler A pointer to a function of type E=46I=5FCPU= =5FINTERRUPT=5FHANDLER that is called > + when a processor interrupt occurs. If this parameter is NULL, then th= e handler > + will be uninstalled. > + > + =40retval E=46I=5FSUCCESS The handler for the processor interrupt was= successfully installed or uninstalled. > + =40retval E=46I=5FALREADY=5FSTARTED InterruptHandler is not NULL, and= a handler for InterruptType was > + previously installed. > + =40retval E=46I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a= handler for InterruptType was not > + previously installed. > + =40retval E=46I=5FUNSUPPORTED The interrupt specified by InterruptTyp= e is not supported. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuRegisterInterruptHandler ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN E=46I=5FEXCEPTION=5FTYPE InterruptType, > + IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHandler > + ) > +=7B > + return RegisterInterruptHandler (InterruptType, InterruptHandler); > +=7D > + > +/** > + Returns a timer value from one of the CPU's internal timers. There is= no > + inherent time interval between ticks but is a function of the CPU fre= quency. > + > + =40param This - Protocol instance structure. > + =40param TimerIndex - Specifies which CPU timer is requested. > + =40param TimerValue - Pointer to the returned timer value. > + =40param TimerPeriod - A pointer to the amount of time that passes > + in femtoseconds (10-15) for each increment > + of TimerValue. If TimerValue does not > + increment at a predictable rate, then 0 is > + returned. The amount of time that has > + passed between two calls to GetTimerValue() > + can be calculated with the formula > + (TimerValue2 - TimerValue1) * TimerPeriod. > + This parameter is optional and may be NULL. > + > + =40retval E=46I=5FSUCCESS - If the CPU timer count was returned. > + =40retval E=46I=5FUNSUPPORTED - If the CPU does not have any readable= timers. > + =40retval E=46I=5FDEVICE=5FERROR - If an error occurred while reading= the timer. > + =40retval E=46I=5FINVALID=5FPARAMETER - TimerIndex is not valid or Ti= merValue is NULL. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuGetTimerValue ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN UINT32 TimerIndex, > + OUT UINT64 *TimerValue, > + OUT UINT64 *TimerPeriod OPTIONAL > + ) > +=7B > + return E=46I=5FUNSUPPORTED; > +=7D > + > +/** > + This function modifies the attributes for the memory region specified= by BaseAddress and > + Length from their current attributes to the attributes specified by A= ttributes. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + =40param BaseAddress The physical address that is the start address o= f a memory region. > + =40param Length The size in bytes of the memory region. > + =40param Attributes The bit mask of attributes to set for the memory = region. > + > + =40retval E=46I=5FSUCCESS The attributes were set for the memory regi= on. > + =40retval E=46I=5FACCESS=5FDENIED The attributes for the memory resou= rce range specified by > + BaseAddress and Length cannot be modified. > + =40retval E=46I=5FINVALID=5FPARAMETER Length is zero. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES There are not enough system = resources to modify the attributes of > + the memory resource range. > + =40retval E=46I=5FUNSUPPORTED The processor does not support one or m= ore bytes of the memory > + resource range specified by BaseAddress and Length. > + The bit mask of attributes is not support for the memory resource > + range specified by BaseAddress and Length. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuSetMemoryAttributes ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN E=46I=5FPHYSICAL=5FADDRESS BaseAddress, > + IN UINT64 Length, > + IN UINT64 EfiAttributes > + ) > +=7B > + E=46I=5FSTATUS Status; > + UINTN LoongArchAttributes; > + UINTN RegionBaseAddress; > + UINTN RegionLength; > + UINTN RegionLoongArchAttributes; > + > + if ((BaseAddress & (SIZE=5F4KB - 1)) =21=3D 0) =7B > + // Minimum granularity is SIZE=5F4KB (4KB on ARM) > + DEBUG ((DEBUG=5FPAGE, =22CpuSetMemoryAttributes(%lx, %lx, %lx): Minim= um granularity is SIZE=5F4KB=5Cn=22, > + BaseAddress, > + Length, > + EfiAttributes)); > + > + return E=46I=5FUNSUPPORTED; > + =7D > + // Convert the 'Attribute' into LoongArch Attribute > + LoongArchAttributes =3D EfiAttributeToLoongArchAttribute (EfiAttribut= es); > + > + // Get the region starting from 'BaseAddress' and its 'Attribute' > + RegionBaseAddress =3D BaseAddress; > + Status =3D GetLoongArchMemoryRegion (RegionBaseAddress, BaseAddress += Length, > + &RegionLength, &RegionLoongArchAttributes); > + > + LoongArchSetMemoryAttributes (BaseAddress, Length, EfiAttributes); > + // Data & Instruction Caches are flushed when we set new memory attri= butes. > + // So, we only set the attributes if the new region is different. > + if (E=46I=5FERROR (Status) =7C=7C (RegionLoongArchAttributes =21=3D L= oongArchAttributes) =7C=7C > + ((BaseAddress + Length) > (RegionBaseAddress + RegionLength))) > + =7B > + return LoongArchSetMemoryAttributes (BaseAddress, Length, EfiAttribut= es); > + =7D > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + Callback function for idle events. > + > + =40param Event Event whose notification function is being invoked. > + =40param Context The pointer to the notification function's context, > + which is implementation-dependent. > + > + =40param VOID > +**/ > +VOID > +E=46IAPI > +IdleLoopEventCallback ( > + IN E=46I=5FEVENT Event, > + IN VOID *Context > + ) > +=7B > + CpuSleep (); > +=7D > + > +// > +// Globals used to initialize the protocol > +// > +E=46I=5FHANDLE CpuHandle =3D NULL; > +E=46I=5FCPU=5FARCH=5FPROTOCOL Cpu =3D =7B > + Cpu=46lushCpuDataCache, > + CpuEnableInterrupt, > + CpuDisableInterrupt, > + CpuGetInterruptState, > + CpuInit, > + CpuRegisterInterruptHandler, > + CpuGetTimerValue, > + CpuSetMemoryAttributes, > + 0, // NumberOfTimers > + 4, // DmaBufferAlignment > +=7D; > + > +/** > + Initialize the state information for the CPU Architectural Protocol. > + > + =40param ImageHandle Image handle this driver. > + =40param SystemTable Pointer to the System Table. > + > + =40retval E=46I=5FSUCCESS Thread can be successfully created > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES Cannot allocate protocol dat= a structure > + =40retval E=46I=5FDEVICE=5FERROR Cannot create the thread > +**/ > +E=46I=5FSTATUS > +CpuDxeInitialize ( > + IN E=46I=5FHANDLE ImageHandle, > + IN E=46I=5FSYSTEM=5FTABLE *SystemTable > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FEVENT IdleLoopEvent; > + > + InitializeExceptions (&Cpu); > + > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &CpuHandle, > + &gEfiCpuArchProtocolGuid, &Cpu, > + NULL > + ); > + > + // > + // Setup a callback for idle events > + // > + Status =3D gBS->CreateEventEx ( > + EVT=5FNOTI=46Y=5FSIGNAL, > + TPL=5FNOTI=46Y, > + IdleLoopEventCallback, > + NULL, > + &gIdleLoopEventGuid, > + &IdleLoopEvent > + ); > + ASSERT=5FE=46I=5FERROR (Status); > + return Status; > +=7D > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h= b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h > new file mode 100644 > index 0000000000..43cb976aa2 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h > =40=40 -0,0 +1,199 =40=40 > +/** =40file > + CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +=23ifndef CPU=5FDXE=5FH=5F > +=23define CPU=5FDXE=5FH=5F > + > +=23include > + > +/** > + This function registers and enables the handler specified by Interrup= tHandler for a processor > + interrupt or exception type specified by InteruptNum. If InterruptHan= dler is NULL, then the > + handler for the processor interrupt or exception type specified by In= teruptNum is uninstalled. > + The installed handler is called once for each processor interrupt or = exception. > + > + =40param InteruptNum A number of the processor's current interrupt. > + =40param InterruptHandler A pointer to a function of type E=46I=5FCPU= =5FINTERRUPT=5FHANDLER that is called > + when a processor interrupt occurs. If this parameter is NULL, then th= e handler > + will be uninstalled. > + > + =40retval E=46I=5FSUCCESS The handler for the processor interrupt was= successfully installed or uninstalled. > + =40retval E=46I=5FALREADY=5FSTARTED InterruptHandler is not NULL, and= a handler for InteruptNum was > + previously installed. > + =40retval E=46I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a= handler for InteruptNum was not > + previously installed. > + =40retval E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum = is not supported. > +**/ > +E=46I=5FSTATUS > +RegisterInterruptHandler ( > + IN E=46I=5FEXCEPTION=5FTYPE InteruptNum, > + IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHandler > + ); > + > +/** > + This function registers and enables the handler specified by Interrup= tHandler for a processor > + interrupt or exception type specified by InteruptNum. If InterruptHan= dler is NULL, then the > + handler for the processor interrupt or exception type specified by In= teruptNum is uninstalled. > + The installed handler is called once for each processor interrupt or = exception. > + > + =40param InteruptNum A number of the processor's current interrupt. > + =40param InterruptHandler A pointer to a function of type E=46I=5FCPU= =5FINTERRUPT=5FHANDLER that is called > + when a processor interrupt occurs. If this parameter is NULL, then th= e handler > + will be uninstalled. > + > + =40retval E=46I=5FSUCCESS The handler for the processor interrupt was= successfully installed or uninstalled. > + =40retval E=46I=5FALREADY=5FSTARTED InterruptHandler is not NULL, and= a handler for InteruptNum was > + previously installed. > + =40retval E=46I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a= handler for InteruptNum was not > + previously installed. > + =40retval E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum = is not supported. > +**/ > +E=46I=5FSTATUS > +RegisterDebuggerInterruptHandler ( > + IN E=46I=5FEXCEPTION=5FTYPE InteruptNum, > + IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHandler > + ); > + > +/** > + This function modifies the attributes for the memory region specified= by BaseAddress and > + Length from their current attributes to the attributes specified by A= ttributes. > + > + =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance. > + =40param BaseAddress The physical address that is the start address o= f a memory region. > + =40param Length The size in bytes of the memory region. > + =40param Attributes The bit mask of attributes to set for the memory = region. > + > + =40retval E=46I=5FSUCCESS The attributes were set for the memory regi= on. > + =40retval E=46I=5FACCESS=5FDENIED The attributes for the memory resou= rce range specified by > + BaseAddress and Length cannot be modified. > + =40retval E=46I=5FINVALID=5FPARAMETER Length is zero. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES There are not enough system = resources to modify the attributes of > + the memory resource range. > + =40retval E=46I=5FUNSUPPORTED The processor does not support one or m= ore bytes of the memory > + resource range specified by BaseAddress and Length. > + The bit mask of attributes is not support for the memory resource > + range specified by BaseAddress and Length. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +CpuSetMemoryAttributes ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This, > + IN E=46I=5FPHYSICAL=5FADDRESS BaseAddress, > + IN UINT64 Length, > + IN UINT64 Attributes > + ); > + > +/** Exception module initialization > + This function sets the exception base address. > + > + =40param Cpu A pointer to the CPU architecture protocol structure. > + > + =40retval E=46I=5FSUCCESS Initialization succeeded > + =40retval E=46I=5FNOT=5F=46OUND Could not =46ound resources. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES No enough resources. > +**/ > +E=46I=5FSTATUS > +InitializeExceptions ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *Cpu > + ); > + > +/** Common exception entry > + Exception handling is the entry point for the C environment, > + This function does different things depending on the exception type. > + > + =40param SystemContext The system context at the time of the exceptio= n. > + > + =40retval VOID. > +**/ > +VOID > +E=46IAPI > +CommonExceptionEntry ( > + IN OUT E=46I=5FSYSTEM=5FCONTEXT SystemContext > + ); > + > +extern CHAR8 LoongArchException=5B=5D, LoongArchExceptionEnd=5B=5D; > +/** Set Exception Base Address > + > + =40param addr Exception Base Address. > + > + =40retval The Old Exception Base Address. > +**/ > +extern > +UINT64 > +SetEbase ( > + E=46I=5FPHYSICAL=5FADDRESS addr > + ); > +/* > + Load the =46PU with signalling NANS. This bit pattern we're using has= > + the property that no matter whether considered as single or as double= > + precision represents signaling NANS. > + > + =40param fcsr The value to initialize =46CSR0 > + > + =40retval The Old Exception Base Address. > + */ > +extern > +VOID > +Init=46pu ( > + UINT32 fcsr > + ); > + > +/* > + Read Csr EUEN register. > + > + =40param CsrEuen Pointer to the variable used to store the EUEN regis= ter value > + > + =40retval none > + */ > +extern > +VOID > +LoongArchReadqCsrEuen ( > + UINT64 *CsrEuen > + ); > + > +/* > + Write Csr EUEN register. > + > + =40param The value used to write to the EUEN register > + > + =40retval none > + */ > +extern > +VOID > +LoongArchWriteqCsrEuen ( > + UINT64 CsrEuen > + ); > + > +/* > + Enables floating-point unit > + > + =40param VOID > + > + =40retval VOID > + */ > +extern > +VOID > +LoongArchEnable=46pu ( > + VOID > + ); > + > +/* > + Disable floating-point unit > + > + =40param VOID > + > + =40retval VOID > + */ > +extern > +VOID > +LoongArchDisable=46pu ( > + VOID > + ); > + > +=23endif // CPU=5FDXE=5FH=5F > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.i= nf b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf > new file mode 100644 > index 0000000000..96aabfefb8 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf > =40=40 -0,0 +1,59 =40=40 > +=23=23 =40file > +=23 CPU driver installs CPU Architecture Protocol and CPU MP protocol.= > +=23 > +=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.
> +=23 > +=23 SPDX-License-Identifier: BSD-2-Clause-Patent > +=23 > +=23=23 > + > +=5BDefines=5D > + IN=46=5FVERSION =3D 0x00010005 > + BASE=5FNAME =3D CpuDxe > + =46ILE=5FGUID =3D bf954921-25c1-48c0-9bfb-8d0cd7ee92da > + MODULE=5FTYPE =3D DXE=5FDRIVER > + VERSION=5FSTRING =3D 1.0 > + ENTRY=5FPOINT =3D CpuDxeInitialize > + > +=23 > +=23 VALID=5FARCHITECTURES =3D LOONGARCH64 > +=23 > + > +=5BSources.Common=5D > + CpuDxe.c > + CpuDxe.h > + > +=5BSources.LOONGARCH64=5D > + LoongArch64/Exception.c > + LoongArch64/LoongArch.S > + LoongArch64/=46pu.S > + > +=5BPackages=5D > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec > + > +=5BLibraryClasses=5D > + BaseLib > + BaseMemoryLib > + CacheMaintenanceLib > + CpuLib > + DebugLib > + DxeServicesTableLib > + HobLib > + PeCoffGetEntryPointLib > + UefiDriverEntryPoint > + UefiLib > + MmuLib > + > +=5BProtocols=5D > + gEfiCpuArchProtocolGuid > + gEfiMpServiceProtocolGuid > + > +=5BGuids=5D > + gEfiDebugImageInfoTableGuid > + gIdleLoopEventGuid > + > +=5BDepex=5D > + TRUE > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArc= h64/Exception.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Loong= Arch64/Exception.c > new file mode 100644 > index 0000000000..793ae90e4f > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Exc= eption.c > =40=40 -0,0 +1,335 =40=40 > +/** =40file > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - ESTAT - Exception Status > + - EC=46G - Exception Configure > + - ERA - Exception Return Address > + - BADV - Bad Virtual Address > + - BADI - Bad Instructions > + - Epc or EPC or epc - Exception Program Counter > + - pc or PC or pc - Program Counter > + - CRMD - Current Mode > + - PRMD - Previous Mode > + - CsrEuen - Cpu Status Register Extern Unit Enable > + - fpu or fp or =46P - =46loat Point Unit > + - LOONGARCH - Loongson Arch > + - Irq - Interrupt ReQuest > +**/ > + > +=23include =22Library/Cpu.h=22 > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include =22CpuDxe.h=22 > +=23include > +=23include > +=23include > + > +E=46I=5FEXCEPTION=5FCALLBACK gInterruptHandler=5BMAX=5FLOONGARCH=5FINT= ERRUPT + 1=5D; > +E=46I=5FEXCEPTION=5FCALLBACK gDebuggerExceptionHandlers=5BMAX=5FLOONGA= RCH=5FINTERRUPT + 1=5D; > + > +/** > + This function registers and enables the handler specified by Interrup= tHandler for a processor > + interrupt or exception type specified by InteruptNum. If InterruptHan= dler is NULL, then the > + handler for the processor interrupt or exception type specified by In= teruptNum is uninstalled. > + The installed handler is called once for each processor interrupt or = exception. > + > + =40param InteruptNum A number of the processor's current interrupt. > + =40param InterruptHandler A pointer to a function of type E=46I=5FCPU= =5FINTERRUPT=5FHANDLER that is called > + when a processor interrupt occurs. If this parameter is NULL, then th= e handler > + will be uninstalled. > + > + =40retval E=46I=5FSUCCESS The handler for the processor interrupt was= successfully installed or uninstalled. > + =40retval E=46I=5FALREADY=5FSTARTED InterruptHandler is not NULL, and= a handler for InteruptNum was > + previously installed. > + =40retval E=46I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a= handler for InteruptNum was not > + previously installed. > + =40retval E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum = is not supported. > +**/ > +E=46I=5FSTATUS > +RegisterInterruptHandler ( > + IN E=46I=5FEXCEPTION=5FTYPE InteruptNum, > + IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHandler > + ) > +=7B > + if (InteruptNum > MAX=5FLOONGARCH=5FINTERRUPT) =7B > + return E=46I=5FUNSUPPORTED; > + =7D > + > + if ((InterruptHandler =21=3D NULL) > + && (gInterruptHandler=5BInteruptNum=5D =21=3D NULL)) > + =7B > + return E=46I=5FALREADY=5FSTARTED; > + =7D > + > + gInterruptHandler=5BInteruptNum=5D =3D InterruptHandler; > + > + return E=46I=5FSUCCESS; > +=7D > + > +/** > + This function calls the corresponding exception handler based on the = exception type. > + > + =40param SystemContext The system context at the time of the exceptio= n. > + > + =40retval VOID > +**/ > +STATIC VOID > +E=46IAPI > +CommonInterruptHandler ( > + IN OUT E=46I=5FSYSTEM=5FCONTEXT SystemContext > + ) > +=7B > + INT32 Pending; > + INT32 InterruptNum; > + /*Interrupt =5B13-0=5D NMI IPI TI PCOV hw IP10-IP2 soft IP1-IP0*/ > + Pending =3D ((SystemContext.SystemContextLoongArch64->ESTAT) & > + (SystemContext.SystemContextLoongArch64->EC=46G) & 0x1fff); > + for (InterruptNum =3D 0; InterruptNum < MAX=5FLOONGARCH=5FINTERRUPT; = InterruptNum++) =7B > + if (Pending & (1 << InterruptNum)) =7B > + if (gInterruptHandler=5BInterruptNum=5D =21=3D NULL) =7B > + gInterruptHandler=5BInterruptNum=5D (InterruptNum, SystemContext); > + =7D else =7B > + DEBUG ((DEBUG=5FIN=46O, =22Pending: 0x%0x, InterruptNum: 0x%0x=5Cn=22= , Pending, InterruptNum)); > + =7D > + =7D > + =7D > +=7D > + > +/** > + Use the E=46I Debug Image Table to lookup the =46aultAddress and find= which PE/CO=46=46 image > + it came from. As long as the PE/CO=46=46 image contains a debug direc= tory entry a > + string can be returned. =46or EL=46 and Mach-O images the string poin= ts to the Mach-O or EL=46 > + image. Microsoft tools contain a pointer to the PDB file that contain= s the debug information. > + > + =40param =46aultAddress Address to find PE/CO=46=46 image for. > + =40param ImageBase Return load address of found image > + =40param PeCoffSizeOfHeaders Return the size of the PE/CO=46=46 heade= r for the image that was found > + > + =40retval NULL =46aultAddress not in a loaded PE/CO=46=46 image. > + =40retval Path and file name of PE/CO=46=46 image. > +**/ > +CHAR8 * > +GetImageName ( > + IN UINTN =46aultAddress, > + OUT UINTN *ImageBase, > + OUT UINTN *PeCoffSizeOfHeaders > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FDEBUG=5FIMAGE=5FIN=46O=5FTABLE=5FHEADER *DebugTableHeader; > + E=46I=5FDEBUG=5FIMAGE=5FIN=46O *DebugTable; > + UINTN Entry; > + CHAR8 *Address; > + > + Status =3D EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGu= id, (VOID **)&DebugTableHeader); > + if (E=46I=5FERROR (Status)) =7B > + return NULL; > + =7D > + > + DebugTable =3D DebugTableHeader->EfiDebugImageInfoTable; > + if (DebugTable =3D=3D NULL) =7B > + return NULL; > + =7D > + > + Address =3D (CHAR8 *)(UINTN)=46aultAddress; > + for (Entry =3D 0; Entry < DebugTableHeader->TableSize; Entry++, Debug= Table++) =7B > + if (DebugTable->NormalImage =21=3D NULL) =7B > + if ((DebugTable->NormalImage->ImageInfoType =3D=3D E=46I=5FDEBUG=5FIM= AGE=5FIN=46O=5FTYPE=5FNORMAL) && > + (DebugTable->NormalImage->LoadedImageProtocolInstance =21=3D NULL)) =7B= > + if ((Address >=3D (CHAR8 *)DebugTable->NormalImage->LoadedImageProtoc= olInstance->ImageBase) && > + (Address <=3D ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolI= nstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance= ->ImageSize))) =7B > + *ImageBase =3D (UINTN)DebugTable->NormalImage->LoadedImageProtocolIns= tance->ImageBase; > + *PeCoffSizeOfHeaders =3D PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*Imag= eBase); > + return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImag= eProtocolInstance->ImageBase); > + =7D > + =7D > + =7D > + =7D > + return NULL; > +=7D > + > +/** > + pass a file name string that contains the path, return file name. > + > + =40param =46ullName Path and file name > + > + =40retval file name. > +**/ > +STATIC > +CONST CHAR8 * > +BaseName ( > + IN CONST CHAR8 *=46ullName > + ) > +=7B > + CONST CHAR8 *Str; > + > + Str =3D =46ullName + AsciiStrLen (=46ullName); > + > + while (--Str > =46ullName) =7B > + if (*Str =3D=3D '/' =7C=7C *Str =3D=3D '=5C=5C') =7B > + return Str + 1; > + =7D > + =7D > + return Str; > +=7D > + > +/** Default Exception Handler =46unction > + This function is called when an exception occurs that cannot be handl= ed, > + and this function prints the system context information when the inte= rrupt occurred > + > + =40param SystemContext The system context at the time of the exceptio= n. > + > + =40retval VOID. > +**/ > +STATIC > +VOID > +E=46IAPI > +DefaultHandler ( > + IN OUT E=46I=5FSYSTEM=5FCONTEXT SystemContext > + ) > +=7B > + CHAR8 *ImageName; > + UINTN ImageBase; > + UINTN Epc; > + UINTN PeCoffSizeOfHeader; > + > + DEBUG ((DEBUG=5FERROR, =22CRMD 0x%llx=5Cn=22, SystemContext.SystemCon= textLoongArch64->CRMD)); > + DEBUG ((DEBUG=5FERROR, =22PRMD 0x%llx=5Cn=22, SystemContext.SystemCon= textLoongArch64->PRMD)); > + DEBUG ((DEBUG=5FERROR, =22EC=46G 0x%llx=5Cn=22, SystemContext.SystemC= ontextLoongArch64->EC=46G)); > + DEBUG ((DEBUG=5FERROR, =22ESTAT 0x%llx=5Cn=22, SystemContext.SystemCo= ntextLoongArch64->ESTAT)); > + DEBUG ((DEBUG=5FERROR, =22ERA 0x%llx=5Cn=22, SystemContext.SystemCont= extLoongArch64->ERA)); > + DEBUG ((DEBUG=5FERROR, =22BADV 0x%llx=5Cn=22, SystemContext.SystemCon= textLoongArch64->BADV)); > + DEBUG ((DEBUG=5FERROR, =22BADI 0x%llx=5Cn=22, SystemContext.SystemCon= textLoongArch64->BADI)); > + > + Epc =3D SystemContext.SystemContextLoongArch64->ERA; > + ImageName =3D GetImageName (Epc, &ImageBase, &PeCoffSizeOfHeader); > + if (ImageName =21=3D NULL) =7B > + DEBUG ((DEBUG=5FERROR, =22PC 0x%012lx (0x%012lx+0x%08x) =5B 0=5D %a=5C= n=22, > + Epc, ImageBase, > + Epc - ImageBase, BaseName (ImageName))); > + =7D else =7B > + DEBUG ((DEBUG=5FERROR, =22PC 0x%012lx=5Cn=22, Epc)); > + =7D > + > + while (1); > +=7D > + > +/** Common exception entry > + Exception handling is the entry point for the C environment, > + This function does different things depending on the exception type. > + > + =40param SystemContext The system context at the time of the exceptio= n. > + > + =40retval VOID. > +**/ > +VOID > +E=46IAPI > +CommonExceptionEntry ( > + IN OUT E=46I=5FSYSTEM=5FCONTEXT SystemContext > + ) > +=7B > + INT32 ExceptionType; > + UINT64 CsrEuen; > + UINT64 =46puStatus; > + > + ExceptionType =3D SystemContext.SystemContextLoongArch64->ESTAT & CSR= =5FESTAT=5FEXC; > + ExceptionType =3D ExceptionType >> CSR=5FESTAT=5FEXC=5FSHI=46T; > + > + LoongArchReadqCsrEuen (&CsrEuen); > + =46puStatus =3D CsrEuen & CSR=5FEUEN=5F=46PEN; > + switch (ExceptionType) =7B > + case EXC=5FINT: > + /* > + * handle interrupt exception > + */ > + CommonInterruptHandler (SystemContext); > + if (=21=46puStatus) =7B > + LoongArchReadqCsrEuen (&CsrEuen); > + if (CsrEuen & CSR=5FEUEN=5F=46PEN) =7B > + /* > + * Since Hw =46P is enabled during interrupt handler, > + * disable =46P > + */ > + CsrEuen &=3D =7ECSR=5FEUEN=5F=46PEN; > + LoongArchWriteqCsrEuen (CsrEuen); > + =7D > + =7D > + break; > + case EXC=5F=46PDIS: > + /* > + * Hardware =46P disabled exception, > + * Enable and init =46P registers here > + */ > + LoongArchEnable=46pu (); > + Init=46pu(=46PU=5FCSR=5FRN); > + break; > + default: > + DefaultHandler(SystemContext); > + break; > + =7D > +=7D > + > +/** Exception module initialization > + This function sets the exception base address. > + > + =40param Cpu A pointer to the CPU architecture protocol structure. > + > + =40retval E=46I=5FSUCCESS Initialization succeeded > + =40retval E=46I=5FNOT=5F=46OUND Could not =46ound resources. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES No enough resources. > +**/ > +E=46I=5FSTATUS > +InitializeExceptions ( > + IN E=46I=5FCPU=5FARCH=5FPROTOCOL *Cpu > + ) > +=7B > + E=46I=5FSTATUS Status; > + BOOLEAN IrqEnabled; > + E=46I=5FPHYSICAL=5FADDRESS Address; > + > + ZeroMem (gInterruptHandler, sizeof (*gInterruptHandler)); > + > + // > + // Disable interrupts > + // > + Cpu->GetInterruptState (Cpu, &IrqEnabled); > + Cpu->DisableInterrupt (Cpu); > + > + // > + // E=46I does not use the =46IQ, but a debugger might so we must disa= ble > + // as we take over the exception vectors. > + // > + Status =3D gBS->AllocatePages ( > + AllocateAnyPages, > + EfiRuntimeServicesData, > + 1, > + &Address > + ); > + if (E=46I=5FERROR (Status)) =7B > + return Status; > + =7D > + > + DEBUG ((DEBUG=5FIN=46O, =22Set Exception Base Address=5Cn=22)); > + CopyMem ((char *)Address, LoongArchException, (LoongArchExceptionEnd = - LoongArchException)); > + InvalidateInstructionCacheRange ((char *)Address, (LoongArchException= End - LoongArchException)); > + > + SetEbase (Address); > + DEBUG ((DEBUG=5FIN=46O, =22LoongArchException address: 0x%p=5Cn=22, A= ddress)); > + DEBUG ((DEBUG=5FIN=46O, =22LoongArchExceptionEnd address: 0x%p=5Cn=22= , Address + (LoongArchExceptionEnd - LoongArchException))); > + > + DEBUG ((DEBUG=5FIN=46O, =22InitializeExceptions, IrqEnabled =3D %x=5C= n=22, IrqEnabled)); > + if (IrqEnabled) =7B > + // > + // Restore interrupt state > + // > + Status =3D Cpu->EnableInterrupt (Cpu); > + =7D > + return Status; > +=7D > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArc= h64/=46pu.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch= 64/=46pu.S > new file mode 100644 > index 0000000000..79a20c66a2 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/=46= pu.S > =40=40 -0,0 +1,97 =40=40 > +=23-------------------------------------------------------------------= ----------- > +=23 > +=23 =46pu for LoongArch > +=23 > +=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.
> +=23 > +=23 SPDX-License-Identifier: BSD-2-Clause-Patent > +=23 > +=23 =40par Glossary: > +=23 - CsrEuen - Cpu Status Register Extern Unit Enable > +=23 - =46PEN - =46PU Enable > +=23 - fpu or fp or =46P - =46loat Point Unit > +=23-------------------------------------------------------------------= ---------- > +=23ifndef =5F=5FASSEMBLY=5F=5F > +=23define =5F=5FASSEMBLY=5F=5F > +=23endif > +=23include =22Library/Cpu.h=22 > +=23include =22CpuDxe.h=22 > + > +ASM=5FGLOBAL ASM=5FP=46X(Init=46pu) > +ASM=5FGLOBAL ASM=5FP=46X(LoongArchEnable=46pu) > +ASM=5FGLOBAL ASM=5FP=46X(LoongArchDisable=46pu) > + > +=23 > +=23 Load the =46PU with signalling NANS. This bit pattern we're using = has > +=23 the property that no matter whether considered as single or as dou= ble > +=23 precision represents signaling NANS. > +=23 > +=23 The value to initialize =46CSR0 to comes in =24A0. > +=23 > + > +ASM=5FP=46X(Init=46pu): > + li.d T1, CSR=5FEUEN=5F=46PEN > + csrxchg T1, T1, LOONGARCH=5FCSR=5FEUEN > + > + movgr2fcsr =46CSR0, A0 > + li.d T1, -1 =23 SNaN > + movgr2fr.d =24f0, T1 > + movgr2fr.d =24f1, T1 > + movgr2fr.d =24f2, T1 > + movgr2fr.d =24f3, T1 > + movgr2fr.d =24f4, T1 > + movgr2fr.d =24f5, T1 > + movgr2fr.d =24f6, T1 > + movgr2fr.d =24f7, T1 > + movgr2fr.d =24f8, T1 > + movgr2fr.d =24f9, T1 > + movgr2fr.d =24f10, T1 > + movgr2fr.d =24f11, T1 > + movgr2fr.d =24f12, T1 > + movgr2fr.d =24f13, T1 > + movgr2fr.d =24f14, T1 > + movgr2fr.d =24f15, T1 > + movgr2fr.d =24f16, T1 > + movgr2fr.d =24f17, T1 > + movgr2fr.d =24f18, T1 > + movgr2fr.d =24f19, T1 > + movgr2fr.d =24f20, T1 > + movgr2fr.d =24f21, T1 > + movgr2fr.d =24f22, T1 > + movgr2fr.d =24f23, T1 > + movgr2fr.d =24f24, T1 > + movgr2fr.d =24f25, T1 > + movgr2fr.d =24f26, T1 > + movgr2fr.d =24f27, T1 > + movgr2fr.d =24f28, T1 > + movgr2fr.d =24f29, T1 > + movgr2fr.d =24f30, T1 > + movgr2fr.d =24f31, T1 > + > + jirl ZERO, RA, 0 > + > +=23 > +=23 Enables floating-point unit > +=23 =40param VOID > +=23 =40retval VOID > +=23 > + > +ASM=5FP=46X(LoongArchEnable=46pu): > + li.d T0, 1 > + li.d T1, CSR=5FEUEN=5F=46PEN=5FSHI=46T > + sll.d T0, T0, T1 > + csrxchg T0, T0, LOONGARCH=5FCSR=5FEUEN > + jirl ZERO, RA,0 > + > +=23 > +=23 Disable floating-point unit > +=23 =40param VOID > +=23 =40retval VOID > +=23 > + > +ASM=5FP=46X(LoongArchDisable=46pu): > + li.d T0, 1 > + li.d T1, CSR=5FEUEN=5F=46PEN=5FSHI=46T > + sll.d T0, T0, T1 > + csrxchg ZERO, T0, LOONGARCH=5FCSR=5FEUEN > + jirl ZERO, RA,0 > diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArc= h64/LoongArch.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Loong= Arch64/LoongArch.S > new file mode 100644 > index 0000000000..e463cf44f2 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Loo= ngArch.S > =40=40 -0,0 +1,321 =40=40 > +=23-------------------------------------------------------------------= ----------- > +=23 > +=23 LoongArch for LoongArch > +=23 > +=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.
> +=23 > +=23 SPDX-License-Identifier: BSD-2-Clause-Patent > +=23 > +=23 =40par Glossary: > +=23 - CsrEuen - Cpu Status Register Extern Unit Enable > +=23 - fpu - =46loat Point Unit > +=23 - LOONGARCH - Loongson Arch > +=23 - Ebase - Exception Base Address > +=23-------------------------------------------------------------------= ---------- > + > +=23ifndef =5F=5FASSEMBLY=5F=5F > +=23define =5F=5FASSEMBLY=5F=5F > +=23endif > + > +=23include =22Library/Cpu.h=22 > +=23include =22CpuDxe.h=22 > + > +=23define RSIZE 8 /* 64 bit mode register size */ > +=23define RLOGSIZE 3 > + > +ASM=5FGLOBAL ASM=5FP=46X(Exception=5Fhandler) > +ASM=5FGLOBAL ASM=5FP=46X(LoongArchException) > +ASM=5FGLOBAL ASM=5FP=46X(SetEbase) > +ASM=5FGLOBAL ASM=5FP=46X(LoongArchReadqCsrEuen) > +ASM=5FGLOBAL ASM=5FP=46X(LoongArchWriteqCsrEuen) > + > +=23 > +=23 Main exception handler. Not really a leaf routine but not a normal= > +=23 function either. Save away the entire cpu state end enter exceptio= n mode. > +=23 > + > +ASM=5FP=46X(Exception=5Fhandler): > + csrrd SP, LOONGARCH=5FCSR=5FKS1 > + > + addi.d T0, =24r0, -0x10 > + and SP, SP, T0 > + addi.d SP, SP, -((CSR=5FNUM + BASE=5FNUM + =46P=5FBASE=5FNUM) * RSIZE= ) > + > + st.d RA, SP, RA=5FNUM * RSIZE > + st.d GP, SP, GP=5FNUM * RSIZE > + st.d A0, SP, A0=5FNUM * RSIZE > + st.d A1, SP, A1=5FNUM * RSIZE > + st.d A2, SP, A2=5FNUM * RSIZE > + st.d A3, SP, A3=5FNUM * RSIZE > + st.d A4, SP, A4=5FNUM * RSIZE > + st.d A5, SP, A5=5FNUM * RSIZE > + st.d A6, SP, A6=5FNUM * RSIZE > + st.d A7, SP, A7=5FNUM * RSIZE > + st.d T1, SP, T1=5FNUM * RSIZE > + st.d T2, SP, T2=5FNUM * RSIZE > + st.d T3, SP, T3=5FNUM * RSIZE > + st.d T4, SP, T4=5FNUM * RSIZE > + st.d T5, SP, T5=5FNUM * RSIZE > + st.d T6, SP, T6=5FNUM * RSIZE > + st.d T7, SP, T7=5FNUM * RSIZE > + st.d T8, SP, T8=5FNUM * RSIZE > + st.d TP, SP, TP=5FNUM * RSIZE > + st.d =46P, SP, =46P=5FNUM * RSIZE > + st.d S0, SP, S0=5FNUM * RSIZE > + st.d S1, SP, S1=5FNUM * RSIZE > + st.d S2, SP, S2=5FNUM * RSIZE > + st.d S3, SP, S3=5FNUM * RSIZE > + st.d S4, SP, S4=5FNUM * RSIZE > + st.d S5, SP, S5=5FNUM * RSIZE > + st.d S6, SP, S6=5FNUM * RSIZE > + st.d S7, SP, S7=5FNUM * RSIZE > + st.d S8, SP, S8=5FNUM * RSIZE > + > + =23 > + =23 save T0/SP from scratch registers on stack > + =23 > + csrrd T0, LOONGARCH=5FCSR=5FKS0 > + st.d T0, SP, T0=5FNUM * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FKS1 > + st.d T0, SP, SP=5FNUM * RSIZE > + > + csrrd T0, LOONGARCH=5FCSR=5FCRMD > + st.d T0, SP, (LOONGARCH=5FCSR=5FCRMD + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FPRMD > + st.d T0, SP, (LOONGARCH=5FCSR=5FPRMD + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FEC=46G > + st.d T0, SP, (LOONGARCH=5FCSR=5FEC=46G + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FESTAT > + st.d T0, SP, (LOONGARCH=5FCSR=5FESTAT + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FEPC > + st.d T0, SP, (LOONGARCH=5FCSR=5FEPC+ BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FBADV > + st.d T0, SP, (LOONGARCH=5FCSR=5FBADV + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FBADI > + st.d T0, SP, (LOONGARCH=5FCSR=5FBADI + BASE=5FNUM) * RSIZE > + csrrd T0, LOONGARCH=5FCSR=5FEUEN > + st.d T0, SP, (LOONGARCH=5FCSR=5FEUEN + BASE=5FNUM) * RSIZE > + > + =23 > + =23 Save =46PU context > + =23 > + ori T1, ZERO, CSR=5FEUEN=5F=46PEN > + and T2, T0, T1 > + beqz T2, 1f > + > + fst.d =24f0, SP, (=46P0=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f1, SP, (=46P1=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f2, SP, (=46P2=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f3, SP, (=46P3=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f4, SP, (=46P4=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f5, SP, (=46P5=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f6, SP, (=46P6=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f7, SP, (=46P7=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f8, SP, (=46P8=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f9, SP, (=46P9=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f10, SP, (=46P10=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f11, SP, (=46P11=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f12, SP, (=46P12=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f13, SP, (=46P13=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f14, SP, (=46P14=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f15, SP, (=46P15=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f16, SP, (=46P16=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f17, SP, (=46P17=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f18, SP, (=46P18=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f19, SP, (=46P19=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f20, SP, (=46P20=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f21, SP, (=46P21=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f22, SP, (=46P22=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f23, SP, (=46P23=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f24, SP, (=46P24=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f25, SP, (=46P25=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f26, SP, (=46P26=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f27, SP, (=46P27=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f28, SP, (=46P28=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f29, SP, (=46P29=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f30, SP, (=46P30=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fst.d =24f31, SP, (=46P31=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + > + movfcsr2gr T3, =46CSR0 > + st.d T3, SP, (=46CSR=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + movcf2gr T3, =24fcc0 > + or T2, T3, ZERO > + movcf2gr T3, =24fcc1 > + bstrins.d T2, T3, 0xf, 0x8 > + movcf2gr T3, =24fcc2 > + bstrins.d T2, T3, 0x17, 0x10 > + movcf2gr T3, =24fcc3 > + bstrins.d T2, T3, 0x1f, 0x18 > + movcf2gr T3, =24fcc4 > + bstrins.d T2, T3, 0x27, 0x20 > + movcf2gr T3, =24fcc5 > + bstrins.d T2, T3, 0x2f, 0x28 > + movcf2gr T3, =24fcc6 > + bstrins.d T2, T3, 0x37, 0x30 > + movcf2gr T3, =24fcc7 > + bstrins.d T2, T3, 0x3f, 0x38 > + st.d T2, SP, (=46CC=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > +1: > + or A0, SP, ZERO > + bl CommonExceptionEntry > + /*disable interrupt*/ > + li.d T0, (1 << 2) > + csrxchg ZERO, T0, LOONGARCH=5FCSR=5FCRMD > + > + ld.d T0, SP, (LOONGARCH=5FCSR=5FPRMD + BASE=5FNUM) * RSIZE > + csrwr T0, LOONGARCH=5FCSR=5FPRMD > + ld.d T0, SP, (LOONGARCH=5FCSR=5FEC=46G + BASE=5FNUM) * RSIZE > + csrwr T0, LOONGARCH=5FCSR=5FEC=46G > + ld.d T0, SP, (LOONGARCH=5FCSR=5FEPC + BASE=5FNUM) * RSIZE > + csrwr T0, LOONGARCH=5FCSR=5FEPC > + > + ld.d T0, SP, (LOONGARCH=5FCSR=5FEUEN + BASE=5FNUM) * RSIZE > + ori T1, ZERO, CSR=5FEUEN=5F=46PEN > + and T2, T0, T1 > + beqz T2, 2f > + > + =23 > + =23 check previous =46P state > + =23 restore =46P contect if =46P enabled > + =23 > + fld.d =24f0, SP, (=46P0=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f1, SP, (=46P1=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f2, SP, (=46P2=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f3, SP, (=46P3=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f4, SP, (=46P4=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f5, SP, (=46P5=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f6, SP, (=46P6=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f7, SP, (=46P7=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f8, SP, (=46P8=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f9, SP, (=46P9=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f10, SP, (=46P10=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f11, SP, (=46P11=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f12, SP, (=46P12=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f13, SP, (=46P13=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f14, SP, (=46P14=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f15, SP, (=46P15=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f16, SP, (=46P16=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f17, SP, (=46P17=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f18, SP, (=46P18=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f19, SP, (=46P19=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f20, SP, (=46P20=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f21, SP, (=46P21=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f22, SP, (=46P22=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f23, SP, (=46P23=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f24, SP, (=46P24=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f25, SP, (=46P25=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f26, SP, (=46P26=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f27, SP, (=46P27=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f28, SP, (=46P28=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f29, SP, (=46P29=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f30, SP, (=46P30=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + fld.d =24f31, SP, (=46P31=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + > + ld.d T0, SP, (=46CSR=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + movgr2fcsr =46CSR0, T0 > + ld.d T0, SP, (=46CC=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE > + bstrpick.d T1, T0, 7, 0 > + movgr2cf =24fcc0, T1 > + bstrpick.d T1, T0, 15, 8 > + movgr2cf =24fcc1, T1 > + bstrpick.d T1, T0, 23, 16 > + movgr2cf =24fcc2, T1 > + bstrpick.d T1, T0, 31, 24 > + movgr2cf =24fcc3, T1 > + bstrpick.d T1, T0, 39, 32 > + movgr2cf =24fcc4, T1 > + bstrpick.d T1, T0, 47, 40 > + movgr2cf =24fcc5, T1 > + bstrpick.d T1, T0, 55, 48 > + movgr2cf =24fcc6, T1 > + bstrpick.d T1, T0, 63, 56 > + movgr2cf =24fcc7, T1 > +2: > + ld.d RA, SP, RA=5FNUM * RSIZE > + ld.d GP, SP, GP=5FNUM * RSIZE > + ld.d A0, SP, A0=5FNUM * RSIZE > + ld.d A1, SP, A1=5FNUM * RSIZE > + ld.d A2, SP, A2=5FNUM * RSIZE > + ld.d A3, SP, A3=5FNUM * RSIZE > + ld.d A4, SP, A4=5FNUM * RSIZE > + ld.d A5, SP, A5=5FNUM * RSIZE > + ld.d A6, SP, A6=5FNUM * RSIZE > + ld.d A7, SP, A7=5FNUM * RSIZE > + ld.d T0, SP, T0=5FNUM * RSIZE > + ld.d T1, SP, T1=5FNUM * RSIZE > + ld.d T2, SP, T2=5FNUM * RSIZE > + ld.d T3, SP, T3=5FNUM * RSIZE > + ld.d T4, SP, T4=5FNUM * RSIZE > + ld.d T5, SP, T5=5FNUM * RSIZE > + ld.d T6, SP, T6=5FNUM * RSIZE > + ld.d T7, SP, T7=5FNUM * RSIZE > + ld.d T8, SP, T8=5FNUM * RSIZE > + ld.d TP, SP, TP=5FNUM * RSIZE > + ld.d =46P, SP, =46P=5FNUM * RSIZE > + ld.d S0, SP, S0=5FNUM * RSIZE > + ld.d S1, SP, S1=5FNUM * RSIZE > + ld.d S2, SP, S2=5FNUM * RSIZE > + ld.d S3, SP, S3=5FNUM * RSIZE > + ld.d S4, SP, S4=5FNUM * RSIZE > + ld.d S5, SP, S5=5FNUM * RSIZE > + ld.d S6, SP, S6=5FNUM * RSIZE > + ld.d S7, SP, S7=5FNUM * RSIZE > + ld.d S8, SP, S8=5FNUM * RSIZE > + > + ld.d SP, SP, SP=5FNUM * RSIZE > + ertn > + > +=23 > +=23 Exception trampoline copied down to RAM after initialization. > +=23 > + > +ASM=5FP=46X(LoongArchException): > + csrwr T0, LOONGARCH=5FCSR=5FKS0 > + csrwr SP, LOONGARCH=5FCSR=5FKS1 > + pcaddi T0, 0 > + ld.d T0, T0, 16 > + jirl ZERO, T0, 0 > + nop > +1: > + .quad Exception=5Fhandler > +.globl LoongArchExceptionEnd > +LoongArchExceptionEnd: > + > +=23 > +=23 Set Exception Base Address. > +=23 > + > +ASM=5FP=46X(SetEbase): > + =23 > + =23 clear Vint cofigure > + =23 all exceptions share the same interrupt entry > + =23 > + csrrd T0, LOONGARCH=5FCSR=5FEC=46G > + li.d T1, =7E0x70000 > + and T0, T0, T1 > + csrwr T0, LOONGARCH=5FCSR=5FEC=46G > + > + =23 set ebase > + csrwr A0, LOONGARCH=5FCSR=5FEBASE > + jirl ZERO, RA, 0 > + > +=23 > +=23 Read Csr EUEN register. > +=23 =40param A0 Pointer to the variable used to store the EUEN registe= r value > +=23 =40retval none > +=23 > + > +ASM=5FP=46X(LoongArchReadqCsrEuen): > + csrrd T0, LOONGARCH=5FCSR=5FEUEN > + stptr.d T0, A0, 0 > + jirl ZERO, RA,0 > + > +=23 > +=23 Write Csr EUEN register. > +=23 =40param A0 The value used to write to the EUEN register > +=23 =40retval none > +=23 > + > +ASM=5FP=46X(LoongArchWriteqCsrEuen): > + csrwr A0, LOONGARCH=5FCSR=5FEUEN > + jirl ZERO, RA,0 > -- > 2.31.1 --636e1999_50b78e22_1e57b Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline
Reviewed-by: Chao Li  <lichao=40loongson.cn>


Thanks,
Chao
--------

On 11=E6=9C=88 11 2= 022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li <lixianglai=40loongson.cn= > wrote:
The driver produces E=46I=5FCPU=5F= ARCH=5FPROTOCOL,

Initialize the exception entry address.


RE=46: https://bugzilla.tianocore.org/show=5Fbug.cgi=3F= id=3D4054



Cc: Bibo Mao <maobibo=40loongson.cn>= ;

Cc: Chao Li <lichao=40loongson.cn>

Cc= : Leif Lindholm <quic=5Fllindhol=40quicinc.com>

Cc: L= iming Gao <gaoliming=40byosoft.com.cn>

Cc: Michael D = Kinney <michael.d.kinney=40intel.com>

Signed-off-by: = xianglai li <lixianglai=40loongson.cn>

---

<= div>.../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c =7C 367 ++++++++++++++++= ++

.../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h =7C 199 +++= +++++++

.../Drivers/CpuDxe/CpuDxe.inf =7C 59 +++

<= div>.../Drivers/CpuDxe/LoongArch64/Exception.c =7C 335 ++++++++++++++++
.../Drivers/CpuDxe/LoongArch64/=46pu.S =7C 97 +++++
.../Drivers/CpuDxe/LoongArch64/LoongArch.S =7C 321 +++++++++++++++<= /div>
6 files changed, 1378 insertions(+)

create mo= de 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/C= puDxe/CpuDxe.h

create mode 100644 Platform/Loongson/LoongAr= chQemuPkg/Drivers/CpuDxe/CpuDxe.inf

create mode 100644 Plat= form/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Exception.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/= CpuDxe/LoongArch64/=46pu.S

create mode 100644 Platform/Loon= gson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/LoongArch.S


diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/= CpuDxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c
new file mode 100644

index 0000000000..23f824d82= b

--- /dev/null

+++ b/Platform/Loongson/Loong= ArchQemuPkg/Drivers/CpuDxe/CpuDxe.c

=40=40 -0,0 +1,367 =40=40=

+/** =40file

+ CPU DXE Module to produce CPU= ARCH Protocol

+

+ Copyright (c) 2022 Loongso= n Technology Corporation Limited. All rights reserved.<BR>
+

+ SPDX-License-Identifier: BSD-2-Clause-Patent
+

+**/

+

+=23include = <Guid/IdleLoopEvent.h>

+=23include <Uefi.h>
+=23include <Library/CacheMaintenanceLib.h>

+=23include <Library/UefiBootServicesTableLib.h>

+=23= include <Library/CpuLib.h>

+=23include <Library/De= bugLib.h>

+=23include <Library/BaseLib.h>
+=23include <Library/MmuLib.h>

+=23include =22C= puDxe.h=22

+

+BOOLEAN mInterruptState =3D =46= ALSE;

+

+/*

+ This function flu= shes the range of addresses from Start to Start+Length

+ fr= om the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cach= e line boundary

+ are also flushed. If Start+Length is not = aligned to a cache line boundary,

+ then the bytes past Sta= rt+Length to the end of the next cache line boundary

+ are = also flushed. The =46lushType of EfiCpu=46lushTypeWriteBackInvalidate mus= t be

+ supported. If the data cache is fully coherent with = all DMA operations, then

+ this function can just return E=46= I=5FSUCCESS. If the processor does not support

+ flushing a= range of the data cache, then the entire data cache can be flushed.
+

+ =40param This The E=46I=5FCPU=5FARCH=5FPROTOC= OL instance.

+ =40param Start The beginning physical addres= s to flush from the processor's data

+ cache.

+ =40param Length The number of bytes to flush from the processor's data= cache. This

+ function may flush more bytes than Length sp= ecifies depending upon

+ the granularity of the flush opera= tion that the processor supports.

+ =40param =46lushType Sp= ecifies the type of flush operation to perform.

+

=
+ =40retval E=46I=5FSUCCESS The address range from Start to Start+Le= ngth was flushed from

+ the processor's data cache.
+ =40retval E=46I=5FUNSUPPORTEDT The processor does not support th= e cache flush type specified

+ by =46lushType.

+ =40retval E=46I=5FDEVICE=5FERROR The address range from Start to Star= t+Length could not be flushed

+ from the processor's data c= ache.

+**/

+E=46I=5FSTATUS

+E=46= IAPI

+Cpu=46lushCpuDataCache (

+ IN E=46I=5FC= PU=5FARCH=5FPROTOCOL *This,

+ IN E=46I=5FPHYSICAL=5FADDRESS= Start,

+ IN UINT64 Length,

+ IN E=46I=5FCPU=5F= =46LUSH=5FTYPE =46lushType

+ )

+=7B

=
+ switch (=46lushType) =7B

+ case EfiCpu=46lushTypeWri= teBack:

+ WriteBackDataCacheRange ((VOID *) (UINTN)Start, (= UINTN)Length);

+ break;

+ case EfiCpu=46lushT= ypeInvalidate:

+ InvalidateDataCacheRange ((VOID *) (UINTN)= Start, (UINTN)Length);

+ break;

+ case EfiCpu= =46lushTypeWriteBackInvalidate:

+ WriteBackInvalidateDataCa= cheRange ((VOID *) (UINTN)Start, (UINTN)Length);

+ break;
+ default:

+ return E=46I=5FINVALID=5FPARAMETE= R;

+ =7D

+ return E=46I=5FSUCCESS;

<= div>+=7D

+

+/**

+ This function= enables interrupt processing by the processor.

+

=
+ =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance.
+

+ =40retval E=46I=5FSUCCESS Interrupts are enabled = on the processor.

+ =40retval E=46I=5FDEVICE=5FERROR Interr= upts could not be enabled on the processor.

+**/

<= div>+E=46I=5FSTATUS

+E=46IAPI

+CpuEnableInter= rupt (

+ IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This

+ )

+=7B

+ EnableInterrupts ();

<= div>+

+ mInterruptState =3D TRUE;

+ return E=46= I=5FSUCCESS;

+=7D

+

+/**
<= br>
+ This function disables interrupt processing by the processor.
+

+ =40param This The E=46I=5FCPU=5FARCH=5FPRO= TOCOL instance.

+

+ =40retval E=46I=5FSUCCESS= Interrupts are disabled on the processor.

+ =40retval E=46= I=5FDEVICE=5FERROR Interrupts could not be disabled on the processor.
+**/

+E=46I=5FSTATUS

+E=46IAPI
+CpuDisableInterrupt (

+ IN E=46I=5FCPU=5FARCH=5F= PROTOCOL *This

+ )

+=7B

+ Disab= leInterrupts ();

+

+ mInterruptState =3D =46A= LSE;

+ return E=46I=5FSUCCESS;

+=7D

=
+

+/**

+ This function retrieves the pro= cessor's current interrupt state a returns it in

+ State. I= f interrupts are currently enabled, then TRUE is returned. If interrupts<= /div>
+ are currently disabled, then =46ALSE is returned.
+

+ =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL = instance.

+ =40param State A pointer to the processor's cur= rent interrupt state. Set to TRUE if

+ interrupts are enabl= ed and =46ALSE if interrupts are disabled.

+

= + =40retval E=46I=5FSUCCESS The processor's current interrupt state was r= eturned in State.

+ =40retval E=46I=5FINVALID=5FPARAMETER S= tate is NULL.

+**/

+E=46I=5FSTATUS

<= div>+E=46IAPI

+CpuGetInterruptState (

+ IN E=46= I=5FCPU=5FARCH=5FPROTOCOL *This,

+ OUT BOOLEAN *State
=
+ )

+=7B

+ if (State =3D=3D NULL) =7B=

+ return E=46I=5FINVALID=5FPARAMETER;

+ =7D<= /div>
+

+ *State =3D mInterruptState;

+ return E=46I=5FSUCCESS;

+=7D

+

+/**

+ This function generates an INIT on the processor.= If this function succeeds, then the

+ processor will be re= set, and control will not be returned to the caller. If InitType is
=
+ not supported by this processor, or the processor cannot progr= ammatically generate an

+ INIT without help from external h= ardware, then E=46I=5FUNSUPPORTED is returned. If an error

= + occurs attempting to generate an INIT, then E=46I=5FDEVICE=5FERROR is r= eturned.

+

+ =40param This The E=46I=5FCPU=5F= ARCH=5FPROTOCOL instance.

+ =40param InitType The type of p= rocessor INIT to perform.

+

+ =40retval E=46I= =5FSUCCESS The processor INIT was performed. This return code should neve= r be seen.

+ =40retval E=46I=5FUNSUPPORTED The processor IN= IT operation specified by InitType is not supported

+ by th= is processor.

+ =40retval E=46I=5FDEVICE=5FERROR The proces= sor INIT failed.

+**/

+E=46I=5FSTATUS
+E=46IAPI

+CpuInit (

+ IN E=46I=5FCPU=5F= ARCH=5FPROTOCOL *This,

+ IN E=46I=5FCPU=5FINIT=5FTYPE InitT= ype

+ )

+=7B

+ return E=46I=5FU= NSUPPORTED;

+=7D

+

+/**
+ This function registers and enables the handler specified by Int= erruptHandler for a processor

+ interrupt or exception type= specified by InterruptType. If InterruptHandler is NULL, then the
<= br>
+ handler for the processor interrupt or exception type specified= by InterruptType is uninstalled.

+ The installed handler i= s called once for each processor interrupt or exception.

+<= /div>
+ =40param InterruptType Interrupt Type.

+ =40= param InterruptHandler A pointer to a function of type E=46I=5FCPU=5FINTE= RRUPT=5FHANDLER that is called

+ when a processor interrupt= occurs. If this parameter is NULL, then the handler

+ will= be uninstalled.

+

+ =40retval E=46I=5FSUCCES= S The handler for the processor interrupt was successfully installed or u= ninstalled.

+ =40retval E=46I=5FALREADY=5FSTARTED Interrupt= Handler is not NULL, and a handler for InterruptType was

+ = previously installed.

+ =40retval E=46I=5FINVALID=5FPARAMET= ER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.

+ =40retval E=46I=5FUNSUP= PORTED The interrupt specified by InterruptType is not supported.
+**/

+E=46I=5FSTATUS

+E=46IAPI
+CpuRegisterInterruptHandler (

+ IN E=46I=5FCPU=5FAR= CH=5FPROTOCOL *This,

+ IN E=46I=5FEXCEPTION=5FTYPE Interrup= tType,

+ IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHand= ler

+ )

+=7B

+ return RegisterI= nterruptHandler (InterruptType, InterruptHandler);

+=7D
+

+/**

+ Returns a timer value fro= m one of the CPU's internal timers. There is no

+ inherent = time interval between ticks but is a function of the CPU frequency.
=
+

+ =40param This - Protocol instance structure.
+ =40param TimerIndex - Specifies which CPU timer is request= ed.

+ =40param TimerValue - Pointer to the returned timer v= alue.

+ =40param TimerPeriod - A pointer to the amount of t= ime that passes

+ in femtoseconds (10-15) for each incremen= t

+ of TimerValue. If TimerValue does not

+ i= ncrement at a predictable rate, then 0 is

+ returned. The a= mount of time that has

+ passed between two calls to GetTim= erValue()

+ can be calculated with the formula

+ (TimerValue2 - TimerValue1) * TimerPeriod.

+ This param= eter is optional and may be NULL.

+

+ =40retv= al E=46I=5FSUCCESS - If the CPU timer count was returned.

+= =40retval E=46I=5FUNSUPPORTED - If the CPU does not have any readable ti= mers.

+ =40retval E=46I=5FDEVICE=5FERROR - If an error occu= rred while reading the timer.

+ =40retval E=46I=5FINVALID=5F= PARAMETER - TimerIndex is not valid or TimerValue is NULL.

= +**/

+E=46I=5FSTATUS

+E=46IAPI

= +CpuGetTimerValue (

+ IN E=46I=5FCPU=5FARCH=5FPROTOCOL *Thi= s,

+ IN UINT32 TimerIndex,

+ OUT UINT64 *Time= rValue,

+ OUT UINT64 *TimerPeriod OPTIONAL

+ = )

+=7B

+ return E=46I=5FUNSUPPORTED;
+=7D

+

+/**

+ This functi= on modifies the attributes for the memory region specified by BaseAddress= and

+ Length from their current attributes to the attribut= es specified by Attributes.

+

+ =40param This= The E=46I=5FCPU=5FARCH=5FPROTOCOL instance.

+ =40param Bas= eAddress The physical address that is the start address of a memory regio= n.

+ =40param Length The size in bytes of the memory region= .

+ =40param Attributes The bit mask of attributes to set f= or the memory region.

+

+ =40retval E=46I=5FS= UCCESS The attributes were set for the memory region.

+ =40= retval E=46I=5FACCESS=5FDENIED The attributes for the memory resource ran= ge specified by

+ BaseAddress and Length cannot be modified= .

+ =40retval E=46I=5FINVALID=5FPARAMETER Length is zero.
+ =40retval E=46I=5FOUT=5FO=46=5FRESOURCES There are not eno= ugh system resources to modify the attributes of

+ the memo= ry resource range.

+ =40retval E=46I=5FUNSUPPORTED The proc= essor does not support one or more bytes of the memory

+ re= source range specified by BaseAddress and Length.

+ The bit= mask of attributes is not support for the memory resource

= + range specified by BaseAddress and Length.

+**/

=
+E=46I=5FSTATUS

+E=46IAPI

+CpuSetMemoryA= ttributes (

+ IN E=46I=5FCPU=5FARCH=5FPROTOCOL *This,
=
+ IN E=46I=5FPHYSICAL=5FADDRESS BaseAddress,

+ IN = UINT64 Length,

+ IN UINT64 EfiAttributes

+ )<= /div>
+=7B

+ E=46I=5FSTATUS Status;

+= UINTN LoongArchAttributes;

+ UINTN RegionBaseAddress;
+ UINTN RegionLength;

+ UINTN RegionLoongArchAttr= ibutes;

+

+ if ((BaseAddress & (SIZE=5F4K= B - 1)) =21=3D 0) =7B

+ // Minimum granularity is SIZE=5F4K= B (4KB on ARM)

+ DEBUG ((DEBUG=5FPAGE, =22CpuSetMemoryAttri= butes(%lx, %lx, %lx): Minimum granularity is SIZE=5F4KB=5Cn=22,

=
+ BaseAddress,

+ Length,

+ EfiAttributes= ));

+

+ return E=46I=5FUNSUPPORTED;

=
+ =7D

+ // Convert the 'Attribute' into LoongArch Attr= ibute

+ LoongArchAttributes =3D EfiAttributeToLoongArchAttr= ibute (EfiAttributes);

+

+ // Get the region = starting from 'BaseAddress' and its 'Attribute'

+ RegionBas= eAddress =3D BaseAddress;

+ Status =3D GetLoongArchMemoryRe= gion (RegionBaseAddress, BaseAddress + Length,

+ &Regio= nLength, &RegionLoongArchAttributes);

+

+= LoongArchSetMemoryAttributes (BaseAddress, Length, EfiAttributes);
=
+ // Data & Instruction Caches are flushed when we set new m= emory attributes.

+ // So, we only set the attributes if th= e new region is different.

+ if (E=46I=5FERROR (Status) =7C= =7C (RegionLoongArchAttributes =21=3D LoongArchAttributes) =7C=7C
+ ((BaseAddress + Length) > (RegionBaseAddress + RegionLength))= )

+ =7B

+ return LoongArchSetMemoryAttributes= (BaseAddress, Length, EfiAttributes);

+ =7D

= + return E=46I=5FSUCCESS;

+=7D

+

+/**

+ Callback function for idle events.

+=

+ =40param Event Event whose notification function is bein= g invoked.

+ =40param Context The pointer to the notificati= on function's context,

+ which is implementation-dependent.=

+

+ =40param VOID

+**/
+VOID

+E=46IAPI

+IdleLoopEventCallback= (

+ IN E=46I=5FEVENT Event,

+ IN VOID *Conte= xt

+ )

+=7B

+ CpuSleep ();
+=7D

+

+//

+// Global= s used to initialize the protocol

+//

+E=46I=5F= HANDLE CpuHandle =3D NULL;

+E=46I=5FCPU=5FARCH=5FPROTOCOL C= pu =3D =7B

+ Cpu=46lushCpuDataCache,

+ CpuEna= bleInterrupt,

+ CpuDisableInterrupt,

+ CpuGet= InterruptState,

+ CpuInit,

+ CpuRegisterInter= ruptHandler,

+ CpuGetTimerValue,

+ CpuSetMemo= ryAttributes,

+ 0, // NumberOfTimers

+ 4, // = DmaBufferAlignment

+=7D;

+

+/**=

+ Initialize the state information for the CPU Architectur= al Protocol.

+

+ =40param ImageHandle Image h= andle this driver.

+ =40param SystemTable Pointer to the Sy= stem Table.

+

+ =40retval E=46I=5FSUCCESS Thr= ead can be successfully created

+ =40retval E=46I=5FOUT=5FO= =46=5FRESOURCES Cannot allocate protocol data structure

+ =40= retval E=46I=5FDEVICE=5FERROR Cannot create the thread

+**/=

+E=46I=5FSTATUS

+CpuDxeInitialize (
+ IN E=46I=5FHANDLE ImageHandle,

+ IN E=46I=5FSYSTEM=5F= TABLE *SystemTable

+ )

+=7B

+ E= =46I=5FSTATUS Status;

+ E=46I=5FEVENT IdleLoopEvent;
<= br>
+

+ InitializeExceptions (&Cpu);

= +

+ Status =3D gBS->InstallMultipleProtocolInterfaces (<= /div>
+ &CpuHandle,

+ &gEfiCpuArchProtocolG= uid, &Cpu,

+ NULL

+ );

+
+ //

+ // Setup a callback for idle events
+ //

+ Status =3D gBS->CreateEventEx (
+ EVT=5FNOTI=46Y=5FSIGNAL,

+ TPL=5FNOTI=46Y,
+ IdleLoopEventCallback,

+ NULL,

+ &am= p;gIdleLoopEventGuid,

+ &IdleLoopEvent

+ = );

+ ASSERT=5FE=46I=5FERROR (Status);

+ retur= n Status;

+=7D

diff --git a/Platform/Loongson= /LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h b/Platform/Loongson/LoongArchQe= muPkg/Drivers/CpuDxe/CpuDxe.h

new file mode 100644
index 0000000000..43cb976aa2

--- /dev/null

<= div>+++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h
=40=40 -0,0 +1,199 =40=40

+/** =40file

<= div>+ CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol
+

+ Copyright (c) 2022 Loongson Technology Corpo= ration Limited. All rights reserved.<BR>

+

<= div>+ SPDX-License-Identifier: BSD-2-Clause-Patent

+
<= br>
+**/

+

+=23ifndef CPU=5FDXE=5FH=5F
+=23define CPU=5FDXE=5FH=5F

+

+=23= include <Protocol/Cpu.h>

+

+/**
+ This function registers and enables the handler specified by Int= erruptHandler for a processor

+ interrupt or exception type= specified by InteruptNum. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified b= y InteruptNum is uninstalled.

+ The installed handler is ca= lled once for each processor interrupt or exception.

+
+ =40param InteruptNum A number of the processor's current inte= rrupt.

+ =40param InterruptHandler A pointer to a function = of type E=46I=5FCPU=5FINTERRUPT=5FHANDLER that is called

+ = when a processor interrupt occurs. If this parameter is NULL, then the ha= ndler

+ will be uninstalled.

+

= + =40retval E=46I=5FSUCCESS The handler for the processor interrupt was s= uccessfully installed or uninstalled.

+ =40retval E=46I=5FA= LREADY=5FSTARTED InterruptHandler is not NULL, and a handler for Interupt= Num was

+ previously installed.

+ =40retval E= =46I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a handler for In= teruptNum was not

+ previously installed.

+ =40= retval E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum is not = supported.

+**/

+E=46I=5FSTATUS

+RegisterInterruptHandler (

+ IN E=46I=5FEXCEPTION=5FTYPE = InteruptNum,

+ IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER Interru= ptHandler

+ );

+

+/**

=
+ This function registers and enables the handler specified by Inter= ruptHandler for a processor

+ interrupt or exception type s= pecified by InteruptNum. If InterruptHandler is NULL, then the

<= div>+ handler for the processor interrupt or exception type specified by = InteruptNum is uninstalled.

+ The installed handler is call= ed once for each processor interrupt or exception.

+
<= br>
+ =40param InteruptNum A number of the processor's current interr= upt.

+ =40param InterruptHandler A pointer to a function of= type E=46I=5FCPU=5FINTERRUPT=5FHANDLER that is called

+ wh= en a processor interrupt occurs. If this parameter is NULL, then the hand= ler

+ will be uninstalled.

+

+ = =40retval E=46I=5FSUCCESS The handler for the processor interrupt was suc= cessfully installed or uninstalled.

+ =40retval E=46I=5FALR= EADY=5FSTARTED InterruptHandler is not NULL, and a handler for InteruptNu= m was

+ previously installed.

+ =40retval E=46= I=5FINVALID=5FPARAMETER InterruptHandler is NULL, and a handler for Inter= uptNum was not

+ previously installed.

+ =40r= etval E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum is not s= upported.

+**/

+E=46I=5FSTATUS

= +RegisterDebuggerInterruptHandler (

+ IN E=46I=5FEXCEPTION=5F= TYPE InteruptNum,

+ IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER In= terruptHandler

+ );

+

+/**
+ This function modifies the attributes for the memory region s= pecified by BaseAddress and

+ Length from their current att= ributes to the attributes specified by Attributes.

+
<= br>
+ =40param This The E=46I=5FCPU=5FARCH=5FPROTOCOL instance.
=
+ =40param BaseAddress The physical address that is the start ad= dress of a memory region.

+ =40param Length The size in byt= es of the memory region.

+ =40param Attributes The bit mask= of attributes to set for the memory region.

+

+ =40retval E=46I=5FSUCCESS The attributes were set for the memory regi= on.

+ =40retval E=46I=5FACCESS=5FDENIED The attributes for = the memory resource range specified by

+ BaseAddress and Le= ngth cannot be modified.

+ =40retval E=46I=5FINVALID=5FPARA= METER Length is zero.

+ =40retval E=46I=5FOUT=5FO=46=5FRESO= URCES There are not enough system resources to modify the attributes of
+ the memory resource range.

+ =40retval E=46I= =5FUNSUPPORTED The processor does not support one or more bytes of the me= mory

+ resource range specified by BaseAddress and Length.<= /div>
+ The bit mask of attributes is not support for the memory = resource

+ range specified by BaseAddress and Length.
=
+**/

+E=46I=5FSTATUS

+E=46IAPI
=
+CpuSetMemoryAttributes (

+ IN E=46I=5FCPU=5FARCH=5F= PROTOCOL *This,

+ IN E=46I=5FPHYSICAL=5FADDRESS BaseAddress= ,

+ IN UINT64 Length,

+ IN UINT64 Attributes<= /div>
+ );

+

+/** Exception module in= itialization

+ This function sets the exception base addres= s.

+

+ =40param Cpu A pointer to the CPU arch= itecture protocol structure.

+

+ =40retval E=46= I=5FSUCCESS Initialization succeeded

+ =40retval E=46I=5FNO= T=5F=46OUND Could not =46ound resources.

+ =40retval E=46I=5F= OUT=5FO=46=5FRESOURCES No enough resources.

+**/

<= div>+E=46I=5FSTATUS

+InitializeExceptions (

+= IN E=46I=5FCPU=5FARCH=5FPROTOCOL *Cpu

+ );

+=

+/** Common exception entry

+ Exception hand= ling is the entry point for the C environment,

+ This funct= ion does different things depending on the exception type.

= +

+ =40param SystemContext The system context at the time o= f the exception.

+

+ =40retval VOID.
+**/

+VOID

+E=46IAPI

+Com= monExceptionEntry (

+ IN OUT E=46I=5FSYSTEM=5FCONTEXT Syste= mContext

+ );

+

+extern CHAR8 L= oongArchException=5B=5D, LoongArchExceptionEnd=5B=5D;

+/** = Set Exception Base Address

+

+ =40param addr = Exception Base Address.

+

+ =40retval The Old= Exception Base Address.

+**/

+extern
+UINT64

+SetEbase (

+ E=46I=5FPHYSICAL= =5FADDRESS addr

+ );

+/*

+ Load= the =46PU with signalling NANS. This bit pattern we're using has
+ the property that no matter whether considered as single or as d= ouble

+ precision represents signaling NANS.

= +

+ =40param fcsr The value to initialize =46CSR0

=
+

+ =40retval The Old Exception Base Address.
+ */

+extern

+VOID

+Init=46= pu (

+ UINT32 fcsr

+ );

+
=
+/*

+ Read Csr EUEN register.

+
+ =40param CsrEuen Pointer to the variable used to store the EU= EN register value

+

+ =40retval none
+ */

+extern

+VOID

+Loong= ArchReadqCsrEuen (

+ UINT64 *CsrEuen

+ );
+

+/*

+ Write Csr EUEN register.
+

+ =40param The value used to write to the EU= EN register

+

+ =40retval none

= + */

+extern

+VOID

+LoongArchWr= iteqCsrEuen (

+ UINT64 CsrEuen

+ );

=
+

+/*

+ Enables floating-point unit
+

+ =40param VOID

+

+= =40retval VOID

+ */

+extern

+V= OID

+LoongArchEnable=46pu (

+ VOID

<= div>+ );

+

+/*

+ Disable floati= ng-point unit

+

+ =40param VOID

+

+ =40retval VOID

+ */

+exter= n

+VOID

+LoongArchDisable=46pu (

+ VOID

+ );

+

+=23endif // CP= U=5FDXE=5FH=5F

diff --git a/Platform/Loongson/LoongArchQemu= Pkg/Drivers/CpuDxe/CpuDxe.inf b/Platform/Loongson/LoongArchQemuPkg/Driver= s/CpuDxe/CpuDxe.inf

new file mode 100644

inde= x 0000000000..96aabfefb8

--- /dev/null

+++ b/= Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf

=40=40 -0,0 +1,59 =40=40

+=23=23 =40file

+=23= CPU driver installs CPU Architecture Protocol and CPU MP protocol.
=
+=23

+=23 Copyright (c) 2022 Loongson Technology C= orporation Limited. All rights reserved.<BR>

+=23
+=23 SPDX-License-Identifier: BSD-2-Clause-Patent

+=23

+=23=23

+

+=5BDefines=5D=

+ IN=46=5FVERSION =3D 0x00010005

+ BASE=5FNA= ME =3D CpuDxe

+ =46ILE=5FGUID =3D bf954921-25c1-48c0-9bfb-8= d0cd7ee92da

+ MODULE=5FTYPE =3D DXE=5FDRIVER

= + VERSION=5FSTRING =3D 1.0

+ ENTRY=5FPOINT =3D CpuDxeInitia= lize

+

+=23

+=23 VALID=5FARCHIT= ECTURES =3D LOONGARCH64

+=23

+

= +=5BSources.Common=5D

+ CpuDxe.c

+ CpuDxe.h
+

+=5BSources.LOONGARCH64=5D

+ L= oongArch64/Exception.c

+ LoongArch64/LoongArch.S

<= div>+ LoongArch64/=46pu.S

+

+=5BPackages=5D
+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePk= g.dec

+ EmbeddedPkg/EmbeddedPkg.dec

+ Platfor= m/Loongson/LoongArchQemuPkg/Loongson.dec

+

+=5B= LibraryClasses=5D

+ BaseLib

+ BaseMemoryLib
+ CacheMaintenanceLib

+ CpuLib

+= DebugLib

+ DxeServicesTableLib

+ HobLib
+ PeCoffGetEntryPointLib

+ UefiDriverEntryPoint
+ UefiLib

+ MmuLib

+

+=5BProtocols=5D

+ gEfiCpuArchProtocolGuid

+ gEfiMpServiceProtocolGuid

+

+=5BGuids=5D
+ gEfiDebugImageInfoTableGuid

+ gIdleLoopEvent= Guid

+

+=5BDepex=5D

+ TRUE
diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/= LoongArch64/Exception.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuD= xe/LoongArch64/Exception.c

new file mode 100644

index 0000000000..793ae90e4f

--- /dev/null

+++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Exce= ption.c

=40=40 -0,0 +1,335 =40=40

+/** =40fil= e

+

+ Copyright (c) 2022 Loongson Technology = Corporation Limited. All rights reserved.<BR>

+
=
+ SPDX-License-Identifier: BSD-2-Clause-Patent

+
+ =40par Glossary:

+ - ESTAT - Exception Statu= s

+ - EC=46G - Exception Configure

+ - ERA - = Exception Return Address

+ - BADV - Bad Virtual Address
+ - BADI - Bad Instructions

+ - Epc or EPC or ep= c - Exception Program Counter

+ - pc or PC or pc - Program = Counter

+ - CRMD - Current Mode

+ - PRMD - Pr= evious Mode

+ - CsrEuen - Cpu Status Register Extern Unit E= nable

+ - fpu or fp or =46P - =46loat Point Unit

<= div>+ - LOONGARCH - Loongson Arch

+ - Irq - Interrupt ReQue= st

+**/

+

+=23include =22Librar= y/Cpu.h=22

+=23include <Library/BaseMemoryLib.h>
+=23include <Library/UefiBootServicesTableLib.h>
+=23include <Library/UefiLib.h>

+=23include <= ;Library/CacheMaintenanceLib.h>

+=23include <Library/= DebugLib.h>

+=23include =22CpuDxe.h=22

+=23= include <Library/PeCoffGetEntryPointLib.h>

+=23includ= e <Library/UefiLib.h>

+=23include <Guid/DebugImage= InfoTable.h>

+

+E=46I=5FEXCEPTION=5FCALLBA= CK gInterruptHandler=5BMAX=5FLOONGARCH=5FINTERRUPT + 1=5D;

= +E=46I=5FEXCEPTION=5FCALLBACK gDebuggerExceptionHandlers=5BMAX=5FLOONGARC= H=5FINTERRUPT + 1=5D;

+

+/**

+ = This function registers and enables the handler specified by InterruptHan= dler for a processor

+ interrupt or exception type specifie= d by InteruptNum. If InterruptHandler is NULL, then the

+ h= andler for the processor interrupt or exception type specified by Interup= tNum is uninstalled.

+ The installed handler is called once= for each processor interrupt or exception.

+

+ =40param InteruptNum A number of the processor's current interrupt.
+ =40param InterruptHandler A pointer to a function of type E= =46I=5FCPU=5FINTERRUPT=5FHANDLER that is called

+ when a pr= ocessor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.

+

+ =40retv= al E=46I=5FSUCCESS The handler for the processor interrupt was successful= ly installed or uninstalled.

+ =40retval E=46I=5FALREADY=5F= STARTED InterruptHandler is not NULL, and a handler for InteruptNum was
+ previously installed.

+ =40retval E=46I=5FIN= VALID=5FPARAMETER InterruptHandler is NULL, and a handler for InteruptNum= was not

+ previously installed.

+ =40retval = E=46I=5FUNSUPPORTED The interrupt specified by InteruptNum is not support= ed.

+**/

+E=46I=5FSTATUS

+Regis= terInterruptHandler (

+ IN E=46I=5FEXCEPTION=5FTYPE Interup= tNum,

+ IN E=46I=5FCPU=5FINTERRUPT=5FHANDLER InterruptHandl= er

+ )

+=7B

+ if (InteruptNum &= gt; MAX=5FLOONGARCH=5FINTERRUPT) =7B

+ return E=46I=5FUNSUP= PORTED;

+ =7D

+

+ if ((Interrup= tHandler =21=3D NULL)

+ && (gInterruptHandler=5BInt= eruptNum=5D =21=3D NULL))

+ =7B

+ return E=46= I=5FALREADY=5FSTARTED;

+ =7D

+

= + gInterruptHandler=5BInteruptNum=5D =3D InterruptHandler;

= +

+ return E=46I=5FSUCCESS;

+=7D

+

+/**

+ This function calls the correspond= ing exception handler based on the exception type.

+
<= br>
+ =40param SystemContext The system context at the time of the ex= ception.

+

+ =40retval VOID

+**= /

+STATIC VOID

+E=46IAPI

+Commo= nInterruptHandler (

+ IN OUT E=46I=5FSYSTEM=5FCONTEXT Syste= mContext

+ )

+=7B

+ INT32 Pendi= ng;

+ INT32 InterruptNum;

+ /*Interrupt =5B13= -0=5D NMI IPI TI PCOV hw IP10-IP2 soft IP1-IP0*/

+ Pending = =3D ((SystemContext.SystemContextLoongArch64->ESTAT) &

+ (SystemContext.SystemContextLoongArch64->EC=46G) & 0x1fff);
+ for (InterruptNum =3D 0; InterruptNum < MAX=5FLOONGARCH= =5FINTERRUPT; InterruptNum++) =7B

+ if (Pending & (1 &l= t;< InterruptNum)) =7B

+ if (gInterruptHandler=5BInterru= ptNum=5D =21=3D NULL) =7B

+ gInterruptHandler=5BInterruptNu= m=5D (InterruptNum, SystemContext);

+ =7D else =7B
+ DEBUG ((DEBUG=5FIN=46O, =22Pending: 0x%0x, InterruptNum: 0x%0x=5C= n=22, Pending, InterruptNum));

+ =7D

+ =7D
+ =7D

+=7D

+

+/**
+ Use the E=46I Debug Image Table to lookup the =46aultAddre= ss and find which PE/CO=46=46 image

+ it came from. As long= as the PE/CO=46=46 image contains a debug directory entry a

+ string can be returned. =46or EL=46 and Mach-O images the string poin= ts to the Mach-O or EL=46

+ image. Microsoft tools contain = a pointer to the PDB file that contains the debug information.

<= div>+

+ =40param =46aultAddress Address to find PE/CO=46=46= image for.

+ =40param ImageBase Return load address of fou= nd image

+ =40param PeCoffSizeOfHeaders Return the size of = the PE/CO=46=46 header for the image that was found

+
=
+ =40retval NULL =46aultAddress not in a loaded PE/CO=46=46 imag= e.

+ =40retval Path and file name of PE/CO=46=46 image.
+**/

+CHAR8 *

+GetImageName (
+ IN UINTN =46aultAddress,

+ OUT UINTN *ImageBase= ,

+ OUT UINTN *PeCoffSizeOfHeaders

+ )
<= br>
+=7B

+ E=46I=5FSTATUS Status;

+ E=46I= =5FDEBUG=5FIMAGE=5FIN=46O=5FTABLE=5FHEADER *DebugTableHeader;

+ E=46I=5FDEBUG=5FIMAGE=5FIN=46O *DebugTable;

+ UINTN En= try;

+ CHAR8 *Address;

+

+ Stat= us =3D EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, = (VOID **)&DebugTableHeader);

+ if (E=46I=5FERROR (Statu= s)) =7B

+ return NULL;

+ =7D

+<= /div>
+ DebugTable =3D DebugTableHeader->EfiDebugImageInfoTabl= e;

+ if (DebugTable =3D=3D NULL) =7B

+ return= NULL;

+ =7D

+

+ Address =3D (C= HAR8 *)(UINTN)=46aultAddress;

+ for (Entry =3D 0; Entry <= ; DebugTableHeader->TableSize; Entry++, DebugTable++) =7B

+ if (DebugTable->NormalImage =21=3D NULL) =7B

+ if ((= DebugTable->NormalImage->ImageInfoType =3D=3D E=46I=5FDEBUG=5FIMAGE= =5FIN=46O=5FTYPE=5FNORMAL) &&

+ (DebugTable->Nor= malImage->LoadedImageProtocolInstance =21=3D NULL)) =7B

= + if ((Address >=3D (CHAR8 *)DebugTable->NormalImage->LoadedImag= eProtocolInstance->ImageBase) &&

+ (Address <= =3D ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance-= >ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstanc= e->ImageSize))) =7B

+ *ImageBase =3D (UINTN)DebugTable-&= gt;NormalImage->LoadedImageProtocolInstance->ImageBase;

+ *PeCoffSizeOfHeaders =3D PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*Ima= geBase);

+ return PeCoffLoaderGetPdbPointer (DebugTable->= ;NormalImage->LoadedImageProtocolInstance->ImageBase);

+ =7D

+ =7D

+ =7D

+ =7D
=
+ return NULL;

+=7D

+

= +/**

+ pass a file name string that contains the path, retu= rn file name.

+

+ =40param =46ullName Path an= d file name

+

+ =40retval file name.
+**/

+STATIC

+CONST CHAR8 *

+BaseName (

+ IN CONST CHAR8 *=46ullName

+= )

+=7B

+ CONST CHAR8 *Str;

+
+ Str =3D =46ullName + AsciiStrLen (=46ullName);

+

+ while (--Str > =46ullName) =7B

+ if= (*Str =3D=3D '/' =7C=7C *Str =3D=3D '=5C=5C') =7B

+ return= Str + 1;

+ =7D

+ =7D

+ return = Str;

+=7D

+

+/** Default Except= ion Handler =46unction

+ This function is called when an ex= ception occurs that cannot be handled,

+ and this function = prints the system context information when the interrupt occurred
+

+ =40param SystemContext The system context at the= time of the exception.

+

+ =40retval VOID.
+**/

+STATIC

+VOID

+E=46IAPI

+DefaultHandler (

+ IN OUT E=46I=5F= SYSTEM=5FCONTEXT SystemContext

+ )

+=7B
=
+ CHAR8 *ImageName;

+ UINTN ImageBase;

+ UINTN Epc;

+ UINTN PeCoffSizeOfHeader;

+=

+ DEBUG ((DEBUG=5FERROR, =22CRMD 0x%llx=5Cn=22, SystemCont= ext.SystemContextLoongArch64->CRMD));

+ DEBUG ((DEBUG=5F= ERROR, =22PRMD 0x%llx=5Cn=22, SystemContext.SystemContextLoongArch64->= PRMD));

+ DEBUG ((DEBUG=5FERROR, =22EC=46G 0x%llx=5Cn=22, S= ystemContext.SystemContextLoongArch64->EC=46G));

+ DEBUG= ((DEBUG=5FERROR, =22ESTAT 0x%llx=5Cn=22, SystemContext.SystemContextLoon= gArch64->ESTAT));

+ DEBUG ((DEBUG=5FERROR, =22ERA 0x%llx= =5Cn=22, SystemContext.SystemContextLoongArch64->ERA));

= + DEBUG ((DEBUG=5FERROR, =22BADV 0x%llx=5Cn=22, SystemContext.SystemConte= xtLoongArch64->BADV));

+ DEBUG ((DEBUG=5FERROR, =22BADI = 0x%llx=5Cn=22, SystemContext.SystemContextLoongArch64->BADI));
+

+ Epc =3D SystemContext.SystemContextLoongArch64-&= gt;ERA;

+ ImageName =3D GetImageName (Epc, &ImageBase, = &PeCoffSizeOfHeader);

+ if (ImageName =21=3D NULL) =7B<= /div>
+ DEBUG ((DEBUG=5FERROR, =22PC 0x%012lx (0x%012lx+0x%08x) =5B= 0=5D %a=5Cn=22,

+ Epc, ImageBase,

+ Epc - Im= ageBase, BaseName (ImageName)));

+ =7D else =7B

+ DEBUG ((DEBUG=5FERROR, =22PC 0x%012lx=5Cn=22, Epc));

+= =7D

+

+ while (1);

+=7D
<= br>
+

+/** Common exception entry

+ Excep= tion handling is the entry point for the C environment,

+ T= his function does different things depending on the exception type.
=
+

+ =40param SystemContext The system context at t= he time of the exception.

+

+ =40retval VOID.=

+**/

+VOID

+E=46IAPI

=
+CommonExceptionEntry (

+ IN OUT E=46I=5FSYSTEM=5FCONT= EXT SystemContext

+ )

+=7B

+ IN= T32 ExceptionType;

+ UINT64 CsrEuen;

+ UINT64= =46puStatus;

+

+ ExceptionType =3D SystemCon= text.SystemContextLoongArch64->ESTAT & CSR=5FESTAT=5FEXC;
+ ExceptionType =3D ExceptionType >> CSR=5FESTAT=5FEXC=5FSHI=46= T;

+

+ LoongArchReadqCsrEuen (&CsrEuen);<= /div>
+ =46puStatus =3D CsrEuen & CSR=5FEUEN=5F=46PEN;
<= br>
+ switch (ExceptionType) =7B

+ case EXC=5FINT:
+ /*

+ * handle interrupt exception

+ */

+ CommonInterruptHandler (SystemContext);

+ if (=21=46puStatus) =7B

+ LoongArchReadqCsrEuen (&= CsrEuen);

+ if (CsrEuen & CSR=5FEUEN=5F=46PEN) =7B
+ /*

+ * Since Hw =46P is enabled during interrup= t handler,

+ * disable =46P

+ */

+ CsrEuen &=3D =7ECSR=5FEUEN=5F=46PEN;

+ LoongArchWri= teqCsrEuen (CsrEuen);

+ =7D

+ =7D

+ break;

+ case EXC=5F=46PDIS:

+ /*
<= br>
+ * Hardware =46P disabled exception,

+ * Enable an= d init =46P registers here

+ */

+ LoongArchEn= able=46pu ();

+ Init=46pu(=46PU=5FCSR=5FRN);

= + break;

+ default:

+ DefaultHandler(SystemCo= ntext);

+ break;

+ =7D

+=7D
+

+/** Exception module initialization

=
+ This function sets the exception base address.

+
+ =40param Cpu A pointer to the CPU architecture protocol stru= cture.

+

+ =40retval E=46I=5FSUCCESS Initiali= zation succeeded

+ =40retval E=46I=5FNOT=5F=46OUND Could no= t =46ound resources.

+ =40retval E=46I=5FOUT=5FO=46=5FRESOU= RCES No enough resources.

+**/

+E=46I=5FSTATU= S

+InitializeExceptions (

+ IN E=46I=5FCPU=5F= ARCH=5FPROTOCOL *Cpu

+ )

+=7B

+= E=46I=5FSTATUS Status;

+ BOOLEAN IrqEnabled;

+ E=46I=5FPHYSICAL=5FADDRESS Address;

+

+ Ze= roMem (gInterruptHandler, sizeof (*gInterruptHandler));

+
+ //

+ // Disable interrupts

+ /= /

+ Cpu->GetInterruptState (Cpu, &IrqEnabled);
=
+ Cpu->DisableInterrupt (Cpu);

+

= + //

+ // E=46I does not use the =46IQ, but a debugger migh= t so we must disable

+ // as we take over the exception vec= tors.

+ //

+ Status =3D gBS->AllocatePages= (

+ AllocateAnyPages,

+ EfiRuntimeServicesDa= ta,

+ 1,

+ &Address

+ );
+ if (E=46I=5FERROR (Status)) =7B

+ return Stat= us;

+ =7D

+

+ DEBUG ((DEBUG=5FI= N=46O, =22Set Exception Base Address=5Cn=22));

+ CopyMem ((= char *)Address, LoongArchException, (LoongArchExceptionEnd - LoongArchExc= eption));

+ InvalidateInstructionCacheRange ((char *)Addres= s, (LoongArchExceptionEnd - LoongArchException));

+
+ SetEbase (Address);

+ DEBUG ((DEBUG=5FIN=46O, =22L= oongArchException address: 0x%p=5Cn=22, Address));

+ DEBUG = ((DEBUG=5FIN=46O, =22LoongArchExceptionEnd address: 0x%p=5Cn=22, Address = + (LoongArchExceptionEnd - LoongArchException)));

+
+ DEBUG ((DEBUG=5FIN=46O, =22InitializeExceptions, IrqEnabled =3D = %x=5Cn=22, IrqEnabled));

+ if (IrqEnabled) =7B

+ //

+ // Restore interrupt state

+ //
+ Status =3D Cpu->EnableInterrupt (Cpu);

+ =7D=

+ return Status;

+=7D

diff --g= it a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/=46pu.= S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/=46pu.S=

new file mode 100644

index 0000000000..79a20= c66a2

--- /dev/null

+++ b/Platform/Loongson/L= oongArchQemuPkg/Drivers/CpuDxe/LoongArch64/=46pu.S

=40=40 -= 0,0 +1,97 =40=40

+=23--------------------------------------= ----------------------------------------

+=23

+=23 =46pu for LoongArch

+=23

+=23 Copyright= (c) 2022 Loongson Technology Corporation Limited. All rights reserved.&l= t;BR>

+=23

+=23 SPDX-License-Identifier: B= SD-2-Clause-Patent

+=23

+=23 =40par Glossary:=

+=23 - CsrEuen - Cpu Status Register Extern Unit Enable
+=23 - =46PEN - =46PU Enable

+=23 - fpu or fp o= r =46P - =46loat Point Unit

+=23---------------------------= --------------------------------------------------

+=23ifnd= ef =5F=5FASSEMBLY=5F=5F

+=23define =5F=5FASSEMBLY=5F=5F
+=23endif

+=23include =22Library/Cpu.h=22
<= br>
+=23include =22CpuDxe.h=22

+

+ASM=5FG= LOBAL ASM=5FP=46X(Init=46pu)

+ASM=5FGLOBAL ASM=5FP=46X(Loon= gArchEnable=46pu)

+ASM=5FGLOBAL ASM=5FP=46X(LoongArchDisabl= e=46pu)

+

+=23

+=23 Load the =46= PU with signalling NANS. This bit pattern we're using has

+= =23 the property that no matter whether considered as single or as double=

+=23 precision represents signaling NANS.

+=23=

+=23 The value to initialize =46CSR0 to comes in =24A0.
+=23

+

+ASM=5FP=46X(Init=46pu):
+ li.d T1, CSR=5FEUEN=5F=46PEN

+ csrxchg T1, T= 1, LOONGARCH=5FCSR=5FEUEN

+

+ movgr2fcsr =46C= SR0, A0

+ li.d T1, -1 =23 SNaN

+ movgr2fr.d =24= f0, T1

+ movgr2fr.d =24f1, T1

+ movgr2fr.d =24= f2, T1

+ movgr2fr.d =24f3, T1

+ movgr2fr.d =24= f4, T1

+ movgr2fr.d =24f5, T1

+ movgr2fr.d =24= f6, T1

+ movgr2fr.d =24f7, T1

+ movgr2fr.d =24= f8, T1

+ movgr2fr.d =24f9, T1

+ movgr2fr.d =24= f10, T1

+ movgr2fr.d =24f11, T1

+ movgr2fr.d = =24f12, T1

+ movgr2fr.d =24f13, T1

+ movgr2fr= .d =24f14, T1

+ movgr2fr.d =24f15, T1

+ movgr= 2fr.d =24f16, T1

+ movgr2fr.d =24f17, T1

+ mo= vgr2fr.d =24f18, T1

+ movgr2fr.d =24f19, T1

+= movgr2fr.d =24f20, T1

+ movgr2fr.d =24f21, T1

+ movgr2fr.d =24f22, T1

+ movgr2fr.d =24f23, T1

=
+ movgr2fr.d =24f24, T1

+ movgr2fr.d =24f25, T1
<= br>
+ movgr2fr.d =24f26, T1

+ movgr2fr.d =24f27, T1
+ movgr2fr.d =24f28, T1

+ movgr2fr.d =24f29, T1<= /div>
+ movgr2fr.d =24f30, T1

+ movgr2fr.d =24f31, = T1

+

+ jirl ZERO, RA, 0

+
=
+=23

+=23 Enables floating-point unit

+=23 =40param VOID

+=23 =40retval VOID

+=23=

+

+ASM=5FP=46X(LoongArchEnable=46pu):
<= br>
+ li.d T0, 1

+ li.d T1, CSR=5FEUEN=5F=46PEN=5FSHI=46= T

+ sll.d T0, T0, T1

+ csrxchg T0, T0, LOONGA= RCH=5FCSR=5FEUEN

+ jirl ZERO, RA,0

+
+=23

+=23 Disable floating-point unit

+= =23 =40param VOID

+=23 =40retval VOID

+=23
+

+ASM=5FP=46X(LoongArchDisable=46pu):
+ li.d T0, 1

+ li.d T1, CSR=5FEUEN=5F=46PEN=5FSHI=46T=

+ sll.d T0, T0, T1

+ csrxchg ZERO, T0, LOONG= ARCH=5FCSR=5FEUEN

+ jirl ZERO, RA,0

diff --gi= t a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/LoongAr= ch.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Loon= gArch.S

new file mode 100644

index 0000000000= ..e463cf44f2

--- /dev/null

+++ b/Platform/Loo= ngson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/LoongArch.S

=40=40 -0,0 +1,321 =40=40

+=23--------------------------= ----------------------------------------------------

+=23
+=23 LoongArch for LoongArch

+=23

+=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.<BR>

+=23

+=23 SPDX-Licen= se-Identifier: BSD-2-Clause-Patent

+=23

+=23 = =40par Glossary:

+=23 - CsrEuen - Cpu Status Register Exter= n Unit Enable

+=23 - fpu - =46loat Point Unit

+=23 - LOONGARCH - Loongson Arch

+=23 - Ebase - Exception = Base Address

+=23------------------------------------------= -----------------------------------

+

+=23ifn= def =5F=5FASSEMBLY=5F=5F

+=23define =5F=5FASSEMBLY=5F=5F
+=23endif

+

+=23include =22Librar= y/Cpu.h=22

+=23include =22CpuDxe.h=22

+
=
+=23define RSIZE 8 /* 64 bit mode register size */

+=23define RLOGSIZE 3

+

+ASM=5FGLOBAL ASM=5F= P=46X(Exception=5Fhandler)

+ASM=5FGLOBAL ASM=5FP=46X(LoongA= rchException)

+ASM=5FGLOBAL ASM=5FP=46X(SetEbase)

=
+ASM=5FGLOBAL ASM=5FP=46X(LoongArchReadqCsrEuen)

+ASM=5F= GLOBAL ASM=5FP=46X(LoongArchWriteqCsrEuen)

+

= +=23

+=23 Main exception handler. Not really a leaf routine= but not a normal

+=23 function either. Save away the entir= e cpu state end enter exception mode.

+=23

+<= /div>
+ASM=5FP=46X(Exception=5Fhandler):

+ csrrd SP= , LOONGARCH=5FCSR=5FKS1

+

+ addi.d T0, =24r0,= -0x10

+ and SP, SP, T0

+ addi.d SP, SP, -((C= SR=5FNUM + BASE=5FNUM + =46P=5FBASE=5FNUM) * RSIZE)

+
=
+ st.d RA, SP, RA=5FNUM * RSIZE

+ st.d GP, SP, GP=5F= NUM * RSIZE

+ st.d A0, SP, A0=5FNUM * RSIZE

+= st.d A1, SP, A1=5FNUM * RSIZE

+ st.d A2, SP, A2=5FNUM * RS= IZE

+ st.d A3, SP, A3=5FNUM * RSIZE

+ st.d A4= , SP, A4=5FNUM * RSIZE

+ st.d A5, SP, A5=5FNUM * RSIZE
+ st.d A6, SP, A6=5FNUM * RSIZE

+ st.d A7, SP, A7= =5FNUM * RSIZE

+ st.d T1, SP, T1=5FNUM * RSIZE

+ st.d T2, SP, T2=5FNUM * RSIZE

+ st.d T3, SP, T3=5FNUM *= RSIZE

+ st.d T4, SP, T4=5FNUM * RSIZE

+ st.d= T5, SP, T5=5FNUM * RSIZE

+ st.d T6, SP, T6=5FNUM * RSIZE
+ st.d T7, SP, T7=5FNUM * RSIZE

+ st.d T8, SP,= T8=5FNUM * RSIZE

+ st.d TP, SP, TP=5FNUM * RSIZE

=
+ st.d =46P, SP, =46P=5FNUM * RSIZE

+ st.d S0, SP, S0=5F= NUM * RSIZE

+ st.d S1, SP, S1=5FNUM * RSIZE

+= st.d S2, SP, S2=5FNUM * RSIZE

+ st.d S3, SP, S3=5FNUM * RS= IZE

+ st.d S4, SP, S4=5FNUM * RSIZE

+ st.d S5= , SP, S5=5FNUM * RSIZE

+ st.d S6, SP, S6=5FNUM * RSIZE
+ st.d S7, SP, S7=5FNUM * RSIZE

+ st.d S8, SP, S8= =5FNUM * RSIZE

+

+ =23

+ =23 sa= ve T0/SP from scratch registers on stack

+ =23

+ csrrd T0, LOONGARCH=5FCSR=5FKS0

+ st.d T0, SP, T0=5FNUM= * RSIZE

+ csrrd T0, LOONGARCH=5FCSR=5FKS1

+ = st.d T0, SP, SP=5FNUM * RSIZE

+

+ csrrd T0, L= OONGARCH=5FCSR=5FCRMD

+ st.d T0, SP, (LOONGARCH=5FCSR=5FCRM= D + BASE=5FNUM) * RSIZE

+ csrrd T0, LOONGARCH=5FCSR=5FPRMD<= /div>
+ st.d T0, SP, (LOONGARCH=5FCSR=5FPRMD + BASE=5FNUM) * RSIZ= E

+ csrrd T0, LOONGARCH=5FCSR=5FEC=46G

+ st.d= T0, SP, (LOONGARCH=5FCSR=5FEC=46G + BASE=5FNUM) * RSIZE

+ = csrrd T0, LOONGARCH=5FCSR=5FESTAT

+ st.d T0, SP, (LOONGARCH= =5FCSR=5FESTAT + BASE=5FNUM) * RSIZE

+ csrrd T0, LOONGARCH=5F= CSR=5FEPC

+ st.d T0, SP, (LOONGARCH=5FCSR=5FEPC+ BASE=5FNUM= ) * RSIZE

+ csrrd T0, LOONGARCH=5FCSR=5FBADV

= + st.d T0, SP, (LOONGARCH=5FCSR=5FBADV + BASE=5FNUM) * RSIZE

+ csrrd T0, LOONGARCH=5FCSR=5FBADI

+ st.d T0, SP, (LOONGA= RCH=5FCSR=5FBADI + BASE=5FNUM) * RSIZE

+ csrrd T0, LOONGARC= H=5FCSR=5FEUEN

+ st.d T0, SP, (LOONGARCH=5FCSR=5FEUEN + BAS= E=5FNUM) * RSIZE

+

+ =23

+ =23 = Save =46PU context

+ =23

+ ori T1, ZERO, CSR=5F= EUEN=5F=46PEN

+ and T2, T0, T1

+ beqz T2, 1f<= /div>
+

+ fst.d =24f0, SP, (=46P0=5FNUM + =46P=5FBA= SE=5FINDEX) * RSIZE

+ fst.d =24f1, SP, (=46P1=5FNUM + =46P=5F= BASE=5FINDEX) * RSIZE

+ fst.d =24f2, SP, (=46P2=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f3, SP, (=46P3=5FNUM += =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f4, SP, (=46P4=5FN= UM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f5, SP, (=46P5= =5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f6, SP, (=46= P6=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f7, SP, = (=46P7=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f8, = SP, (=46P8=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24= f9, SP, (=46P9=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d= =24f10, SP, (=46P10=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+= fst.d =24f11, SP, (=46P11=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

=
+ fst.d =24f12, SP, (=46P12=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fst.d =24f13, SP, (=46P13=5FNUM + =46P=5FBASE=5FINDEX) * RSI= ZE

+ fst.d =24f14, SP, (=46P14=5FNUM + =46P=5FBASE=5FINDEX)= * RSIZE

+ fst.d =24f15, SP, (=46P15=5FNUM + =46P=5FBASE=5F= INDEX) * RSIZE

+ fst.d =24f16, SP, (=46P16=5FNUM + =46P=5FB= ASE=5FINDEX) * RSIZE

+ fst.d =24f17, SP, (=46P17=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f18, SP, (=46P18=5FNUM= + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f19, SP, (=46P19= =5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f20, SP, (= =46P20=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f21,= SP, (=46P21=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24= f22, SP, (=46P22=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst= .d =24f23, SP, (=46P23=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f24, SP, (=46P24=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fst.d =24f25, SP, (=46P25=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fst.d =24f26, SP, (=46P26=5FNUM + =46P=5FBASE=5FINDEX) * R= SIZE

+ fst.d =24f27, SP, (=46P27=5FNUM + =46P=5FBASE=5FINDE= X) * RSIZE

+ fst.d =24f28, SP, (=46P28=5FNUM + =46P=5FBASE=5F= INDEX) * RSIZE

+ fst.d =24f29, SP, (=46P29=5FNUM + =46P=5FB= ASE=5FINDEX) * RSIZE

+ fst.d =24f30, SP, (=46P30=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fst.d =24f31, SP, (=46P31=5FNUM= + =46P=5FBASE=5FINDEX) * RSIZE

+

+ movfcsr2g= r T3, =46CSR0

+ st.d T3, SP, (=46CSR=5FNUM + =46P=5FBASE=5F= INDEX) * RSIZE

+ movcf2gr T3, =24fcc0

+ or T2= , T3, ZERO

+ movcf2gr T3, =24fcc1

+ bstrins.d= T2, T3, 0xf, 0x8

+ movcf2gr T3, =24fcc2

+ bs= trins.d T2, T3, 0x17, 0x10

+ movcf2gr T3, =24fcc3

=
+ bstrins.d T2, T3, 0x1f, 0x18

+ movcf2gr T3, =24fcc4<= /div>
+ bstrins.d T2, T3, 0x27, 0x20

+ movcf2gr T3,= =24fcc5

+ bstrins.d T2, T3, 0x2f, 0x28

+ mov= cf2gr T3, =24fcc6

+ bstrins.d T2, T3, 0x37, 0x30

<= div>+ movcf2gr T3, =24fcc7

+ bstrins.d T2, T3, 0x3f, 0x38
+ st.d T2, SP, (=46CC=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+1:

+ or A0, SP, ZERO

+ bl Commo= nExceptionEntry

+ /*disable interrupt*/

+ li.= d T0, (1 << 2)

+ csrxchg ZERO, T0, LOONGARCH=5FCSR=5F= CRMD

+

+ ld.d T0, SP, (LOONGARCH=5FCSR=5FPRMD= + BASE=5FNUM) * RSIZE

+ csrwr T0, LOONGARCH=5FCSR=5FPRMD
+ ld.d T0, SP, (LOONGARCH=5FCSR=5FEC=46G + BASE=5FNUM) * RSI= ZE

+ csrwr T0, LOONGARCH=5FCSR=5FEC=46G

+ ld.= d T0, SP, (LOONGARCH=5FCSR=5FEPC + BASE=5FNUM) * RSIZE

+ cs= rwr T0, LOONGARCH=5FCSR=5FEPC

+

+ ld.d T0, SP= , (LOONGARCH=5FCSR=5FEUEN + BASE=5FNUM) * RSIZE

+ ori T1, Z= ERO, CSR=5FEUEN=5F=46PEN

+ and T2, T0, T1

+ b= eqz T2, 2f

+

+ =23

+ =23 check = previous =46P state

+ =23 restore =46P contect if =46P enab= led

+ =23

+ fld.d =24f0, SP, (=46P0=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f1, SP, (=46P1=5FNUM += =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f2, SP, (=46P2=5FN= UM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f3, SP, (=46P3= =5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f4, SP, (=46= P4=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f5, SP, = (=46P5=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f6, = SP, (=46P6=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24= f7, SP, (=46P7=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d= =24f8, SP, (=46P8=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ f= ld.d =24f9, SP, (=46P9=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f10, SP, (=46P10=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fld.d =24f11, SP, (=46P11=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fld.d =24f12, SP, (=46P12=5FNUM + =46P=5FBASE=5FINDEX) * R= SIZE

+ fld.d =24f13, SP, (=46P13=5FNUM + =46P=5FBASE=5FINDE= X) * RSIZE

+ fld.d =24f14, SP, (=46P14=5FNUM + =46P=5FBASE=5F= INDEX) * RSIZE

+ fld.d =24f15, SP, (=46P15=5FNUM + =46P=5FB= ASE=5FINDEX) * RSIZE

+ fld.d =24f16, SP, (=46P16=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f17, SP, (=46P17=5FNUM= + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f18, SP, (=46P18= =5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f19, SP, (= =46P19=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f20,= SP, (=46P20=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24= f21, SP, (=46P21=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld= .d =24f22, SP, (=46P22=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f23, SP, (=46P23=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fld.d =24f24, SP, (=46P24=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE
+ fld.d =24f25, SP, (=46P25=5FNUM + =46P=5FBASE=5FINDEX) * R= SIZE

+ fld.d =24f26, SP, (=46P26=5FNUM + =46P=5FBASE=5FINDE= X) * RSIZE

+ fld.d =24f27, SP, (=46P27=5FNUM + =46P=5FBASE=5F= INDEX) * RSIZE

+ fld.d =24f28, SP, (=46P28=5FNUM + =46P=5FB= ASE=5FINDEX) * RSIZE

+ fld.d =24f29, SP, (=46P29=5FNUM + =46= P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f30, SP, (=46P30=5FNUM= + =46P=5FBASE=5FINDEX) * RSIZE

+ fld.d =24f31, SP, (=46P31= =5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+

+ ld.= d T0, SP, (=46CSR=5FNUM + =46P=5FBASE=5FINDEX) * RSIZE

+ mo= vgr2fcsr =46CSR0, T0

+ ld.d T0, SP, (=46CC=5FNUM + =46P=5FB= ASE=5FINDEX) * RSIZE

+ bstrpick.d T1, T0, 7, 0

+ movgr2cf =24fcc0, T1

+ bstrpick.d T1, T0, 15, 8
+ movgr2cf =24fcc1, T1

+ bstrpick.d T1, T0, 23, 16
+ movgr2cf =24fcc2, T1

+ bstrpick.d T1, T0, 31= , 24

+ movgr2cf =24fcc3, T1

+ bstrpick.d T1, = T0, 39, 32

+ movgr2cf =24fcc4, T1

+ bstrpick.= d T1, T0, 47, 40

+ movgr2cf =24fcc5, T1

+ bst= rpick.d T1, T0, 55, 48

+ movgr2cf =24fcc6, T1

+ bstrpick.d T1, T0, 63, 56

+ movgr2cf =24fcc7, T1
+2:

+ ld.d RA, SP, RA=5FNUM * RSIZE

+ = ld.d GP, SP, GP=5FNUM * RSIZE

+ ld.d A0, SP, A0=5FNUM * RSI= ZE

+ ld.d A1, SP, A1=5FNUM * RSIZE

+ ld.d A2,= SP, A2=5FNUM * RSIZE

+ ld.d A3, SP, A3=5FNUM * RSIZE
=
+ ld.d A4, SP, A4=5FNUM * RSIZE

+ ld.d A5, SP, A5=5F= NUM * RSIZE

+ ld.d A6, SP, A6=5FNUM * RSIZE

+= ld.d A7, SP, A7=5FNUM * RSIZE

+ ld.d T0, SP, T0=5FNUM * RS= IZE

+ ld.d T1, SP, T1=5FNUM * RSIZE

+ ld.d T2= , SP, T2=5FNUM * RSIZE

+ ld.d T3, SP, T3=5FNUM * RSIZE
+ ld.d T4, SP, T4=5FNUM * RSIZE

+ ld.d T5, SP, T5= =5FNUM * RSIZE

+ ld.d T6, SP, T6=5FNUM * RSIZE

+ ld.d T7, SP, T7=5FNUM * RSIZE

+ ld.d T8, SP, T8=5FNUM *= RSIZE

+ ld.d TP, SP, TP=5FNUM * RSIZE

+ ld.d= =46P, SP, =46P=5FNUM * RSIZE

+ ld.d S0, SP, S0=5FNUM * RSI= ZE

+ ld.d S1, SP, S1=5FNUM * RSIZE

+ ld.d S2,= SP, S2=5FNUM * RSIZE

+ ld.d S3, SP, S3=5FNUM * RSIZE
=
+ ld.d S4, SP, S4=5FNUM * RSIZE

+ ld.d S5, SP, S5=5F= NUM * RSIZE

+ ld.d S6, SP, S6=5FNUM * RSIZE

+= ld.d S7, SP, S7=5FNUM * RSIZE

+ ld.d S8, SP, S8=5FNUM * RS= IZE

+

+ ld.d SP, SP, SP=5FNUM * RSIZE
+ ertn

+

+=23

+=23 Excep= tion trampoline copied down to RAM after initialization.

+=23=

+

+ASM=5FP=46X(LoongArchException):
+ csrwr T0, LOONGARCH=5FCSR=5FKS0

+ csrwr SP, LOONGAR= CH=5FCSR=5FKS1

+ pcaddi T0, 0

+ ld.d T0, T0, = 16

+ jirl ZERO, T0, 0

+ nop

+1:=

+ .quad Exception=5Fhandler

+.globl LoongArc= hExceptionEnd

+LoongArchExceptionEnd:

+
=
+=23

+=23 Set Exception Base Address.

+=23

+

+ASM=5FP=46X(SetEbase):

+ =23

+ =23 clear Vint cofigure

+ =23 all e= xceptions share the same interrupt entry

+ =23

+ csrrd T0, LOONGARCH=5FCSR=5FEC=46G

+ li.d T1, =7E0x7000= 0

+ and T0, T0, T1

+ csrwr T0, LOONGARCH=5FCS= R=5FEC=46G

+

+ =23 set ebase

+ = csrwr A0, LOONGARCH=5FCSR=5FEBASE

+ jirl ZERO, RA, 0
<= br>
+

+=23

+=23 Read Csr EUEN register.
+=23 =40param A0 Pointer to the variable used to store the E= UEN register value

+=23 =40retval none

+=23
+

+ASM=5FP=46X(LoongArchReadqCsrEuen):
+ csrrd T0, LOONGARCH=5FCSR=5FEUEN

+ stptr.d T0, A0,= 0

+ jirl ZERO, RA,0

+

+=23
+=23 Write Csr EUEN register.

+=23 =40param A0 T= he value used to write to the EUEN register

+=23 =40retval = none

+=23

+

+ASM=5FP=46X(LoongA= rchWriteqCsrEuen):

+ csrwr A0, LOONGARCH=5FCSR=5FEUEN
=
+ jirl ZERO, RA,0

--

2.31.1
--636e1999_50b78e22_1e57b--