// Copyright 2026 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build goexperiment.runtimesecret // Note: this assembly file is used for testing only. // We need to access registers directly to properly test // that secrets are erased and go test doesn't like to conditionally // include assembly files. // These functions defined in the package proper and we // rely on the linker to prune these away in regular builds #include "go_asm.h" #include "funcdata.h" #define REGTMP1 R27 #define REGTMP2 R28 #define dirtyReg(dstReg) \ ADDV $0x1, REGTMP1 \ MOVV REGTMP1, dstReg \ #define dirtyVReg(dstReg) \ ADDV $0x1, REGTMP1 \ VMOVQ REGTMP1, dstReg.V2 \ #define dirtyXReg(dstReg) \ ADDV $0x1, REGTMP1 \ XVMOVQ REGTMP1, dstReg.V4 \ // func loadRegisters(p unsafe.Pointer) TEXT ·loadRegisters(SB),0,$0-8 MOVV p+0(FP), R4 MOVV (R4), R16 MOVV (R4), R17 MOVV (R4), R18 MOVV (R4), R19 MOVD (R4), F20 MOVD (R4), F21 MOVD (R4), F22 MOVD (R4), F23 MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLSX(SB), R5 BEQ R5, return VMOVQ (R4), V24 VMOVQ (R4), V25 VMOVQ (R4), V26 VMOVQ (R4), V27 MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLASX(SB), R5 BEQ R5, return XVMOVQ (R4), X28 XVMOVQ (R4), X29 XVMOVQ (R4), X30 XVMOVQ (R4), X31 return: RET // func spillRegisters(p unsafe.Pointer) uintptr TEXT ·spillRegisters(SB),0,$0-16 MOVV p+0(FP), R4 MOVV $0, R5 MOVV R16, 0(R4) MOVV R17, 8(R4) MOVV R18, 16(R4) MOVV R19, 24(R4) MOVD F20, 32(R4) MOVD F21, 40(R4) MOVD F22, 48(R4) MOVD F23, 56(R4) ADDV $64, R4 ADDV $64, R5 MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLSX(SB), R6 BEQ R6, return VMOVQ V24, 0(R4) VMOVQ V25, 16(R4) VMOVQ V26, 32(R4) VMOVQ V27, 48(R4) ADDV $64, R4 ADDV $64, R5 MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLASX(SB), R6 BEQ R6, return XVMOVQ X28, 0(R4) XVMOVQ X29, 32(R4) XVMOVQ X30, 64(R4) XVMOVQ X31, 96(R4) ADDV $128, R4 ADDV $128, R5 return: MOVV R5, ret+8(FP) RET TEXT ·useSecret(SB),0,$0-24 NO_LOCAL_POINTERS // Load secret into R27 MOVV secret_base+0(FP), REGTMP2 MOVV (REGTMP2), REGTMP1 MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLASX(SB), REGTMP2 BNE REGTMP2, dirtyLASX MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLSX(SB), REGTMP2 BNE REGTMP2, dirtyLSX // Dirty the floating point registers dirtyReg(F0) dirtyReg(F1) dirtyReg(F2) dirtyReg(F3) dirtyReg(F4) dirtyReg(F5) dirtyReg(F6) dirtyReg(F7) dirtyReg(F8) dirtyReg(F9) dirtyReg(F10) dirtyReg(F11) dirtyReg(F12) dirtyReg(F13) dirtyReg(F14) dirtyReg(F15) dirtyReg(F16) dirtyReg(F17) dirtyReg(F18) dirtyReg(F19) dirtyReg(F20) dirtyReg(F21) dirtyReg(F22) dirtyReg(F23) dirtyReg(F24) dirtyReg(F25) dirtyReg(F26) dirtyReg(F27) dirtyReg(F28) dirtyReg(F29) dirtyReg(F30) dirtyReg(F31) JMP dirtyInt // Dirty the lsx registers dirtyLSX: dirtyVReg(V0) dirtyVReg(V1) dirtyVReg(V2) dirtyVReg(V3) dirtyVReg(V4) dirtyVReg(V5) dirtyVReg(V6) dirtyVReg(V7) dirtyVReg(V8) dirtyVReg(V9) dirtyVReg(V10) dirtyVReg(V11) dirtyVReg(V12) dirtyVReg(V13) dirtyVReg(V14) dirtyVReg(V15) dirtyVReg(V16) dirtyVReg(V17) dirtyVReg(V18) dirtyVReg(V19) dirtyVReg(V20) dirtyVReg(V21) dirtyVReg(V22) dirtyVReg(V23) dirtyVReg(V24) dirtyVReg(V25) dirtyVReg(V26) dirtyVReg(V27) dirtyVReg(V28) dirtyVReg(V29) dirtyVReg(V30) dirtyVReg(V31) JMP dirtyInt // Dirty the lasx registers dirtyLASX: dirtyXReg(X0) dirtyXReg(X1) dirtyXReg(X2) dirtyXReg(X3) dirtyXReg(X4) dirtyXReg(X5) dirtyXReg(X6) dirtyXReg(X7) dirtyXReg(X8) dirtyXReg(X9) dirtyXReg(X10) dirtyXReg(X11) dirtyXReg(X12) dirtyXReg(X13) dirtyXReg(X14) dirtyXReg(X15) dirtyXReg(X16) dirtyXReg(X17) dirtyXReg(X18) dirtyXReg(X19) dirtyXReg(X20) dirtyXReg(X21) dirtyXReg(X22) dirtyXReg(X23) dirtyXReg(X24) dirtyXReg(X25) dirtyXReg(X26) dirtyXReg(X27) dirtyXReg(X28) dirtyXReg(X29) dirtyXReg(X30) dirtyXReg(X31) dirtyInt: // Scatter secret across registers. // Increment low byte so we can tell which register // a leaking secret came from. dirtyReg(R4) dirtyReg(R5) dirtyReg(R6) dirtyReg(R7) dirtyReg(R8) dirtyReg(R9) dirtyReg(R10) dirtyReg(R11) dirtyReg(R12) dirtyReg(R13) dirtyReg(R14) dirtyReg(R15) dirtyReg(R16) dirtyReg(R17) dirtyReg(R18) dirtyReg(R19) RET