OvmfPkg/LoongArchVirt: Clear per-CPU KS registers in SEC

The LoongArch KS registers are software scratch state. Firmware cannot
rely on their values being zero after reset, so values written during a
previous boot may be observed as stale data.

The early serial library uses KS1 as a firmware-local UART base cache
and treats a non-zero value as valid. Stale data in KS1 can therefore
be mistaken for the UART MMIO base during the first SEC debug output.

Clear KS0 through KS8 after disabling local interrupts and before
reading the CPU ID. Every CPU entering the SEC module therefore clears
its own scratch-register state before the BSP/AP split. The BSP serial
path then discovers the UART base from the device tree and stores the
valid value in KS1 for the remainder of the firmware boot.

Signed-off-by: Dongyan Qian <qiandongyan@loongson.cn>
Signed-off-by: Chao Li <lichao@loongson.cn>
This commit is contained in:
Dongyan Qian 2026-08-19 09:13:59 +08:00 committed by Chao Li
parent 7735ed4f8e
commit 915b8818b8
2 changed files with 14 additions and 2 deletions

View file

@ -128,8 +128,9 @@ GetSerialRegisterBase (
UINTN SerialRegisterBase;
//
// The LoongArchVirt serial hook path uses KS1 to hand off the UART base.
// Reuse it here to avoid repeated FDT lookups during early debug output.
// SEC initializes KS1 before the first debug output. The LoongArchVirt
// serial hook path then uses it to hand off the UART base. Reuse the value
// here to avoid repeated FDT lookups during early debug output.
//
SerialRegisterBase = CsrRead (LOONGARCH_CSR_KS1);
if (SerialRegisterBase != 0) {

View file

@ -29,6 +29,17 @@ ASM_PFX(_ModuleEntryPoint):
li.w $a0, 0x1FFF
bl DisableLocalInterrupts
/* Clear per-CPU scratch registers left by the previous boot */
csrwr $zero, LOONGARCH_CSR_KS0
csrwr $zero, LOONGARCH_CSR_KS1
csrwr $zero, LOONGARCH_CSR_KS2
csrwr $zero, LOONGARCH_CSR_KS3
csrwr $zero, LOONGARCH_CSR_KS4
csrwr $zero, LOONGARCH_CSR_KS5
csrwr $zero, LOONGARCH_CSR_KS6
csrwr $zero, LOONGARCH_CSR_KS7
csrwr $zero, LOONGARCH_CSR_KS8
/* Read physical cpu number id */
bl GetApicId
li.d $t0, BOOTCORE_ID //0