Files
Konstantin BogomolovandgVisor bot 4cdc108eff KVM: Enable PAC inside of the guest with zeroed keys.
Non-hint PAC instructions will generate a SIGILL even if PAC has never been
enabled in the guest. This is circumvented by enabling PAC in the guest, but
setting all of the PAC keys to zero which effectively makes all PAC instructions
no-ops, as was originally the intention with disabling PAC in KVM in the
first place.

PiperOrigin-RevId: 974001522
2026-08-31 11:58:02 -07:00

192 lines
4.3 KiB
ArmAsm

// Copyright 2019 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build arm64
// test_util_arm64.s provides ARM64 test functions.
#include "funcdata.h"
#include "textflag.h"
#define SYS_GETPID 172
// This function simulates the getpid syscall.
TEXT ·Getpid(SB),NOSPLIT,$0
NO_LOCAL_POINTERS
MOVD $SYS_GETPID, R8
SVC
RET
TEXT ·AddrOfGetpid(SB),NOSPLIT,$0-8
MOVD $·Getpid(SB), R0
MOVD R0, ret+0(FP)
RET
TEXT ·touch(SB),NOSPLIT,$0
start:
MOVD 0(R8), R1
MOVD $SYS_GETPID, R8 // getpid
SVC
B start
TEXT ·AddrOfTouch(SB),NOSPLIT,$0-8
MOVD $·touch(SB), R0
MOVD R0, ret+0(FP)
RET
TEXT ·haltLoop(SB),NOSPLIT,$0
start:
HLT
B start
TEXT ·AddrOfHaltLoop(SB),NOSPLIT,$0-8
MOVD $·haltLoop(SB), R0
MOVD R0, ret+0(FP)
RET
// This function simulates a loop of syscall.
TEXT ·syscallLoop(SB),NOSPLIT,$0
start:
SVC
B start
TEXT ·AddrOfSyscallLoop(SB),NOSPLIT,$0-8
MOVD $·syscallLoop(SB), R0
MOVD R0, ret+0(FP)
RET
TEXT ·spinLoop(SB),NOSPLIT,$0
start:
B start
TEXT ·AddrOfSpinLoop(SB),NOSPLIT,$0-8
MOVD $·spinLoop(SB), R0
MOVD R0, ret+0(FP)
RET
TEXT ·TLSWorks(SB),NOSPLIT,$0
NO_LOCAL_POINTERS
MOVD $0x6789, R5
MSR R5, TPIDR_EL0
MOVD $SYS_GETPID, R8 // getpid
SVC
MRS TPIDR_EL0, R6
CMP R5, R6
BNE isNaN
MOVD $1, R0
MOVD R0, ret+0(FP)
RET
isNaN:
MOVD $0, ret+0(FP)
RET
TEXT ·FloatingPointWorks(SB),NOSPLIT,$0
NO_LOCAL_POINTERS
// gc will touch fpsimd, so we should test it.
// such as in <runtime.deductSweepCredit>.
FMOVD $(9.9), F0
MOVD $SYS_GETPID, R8 // getpid
SVC
FMOVD $(9.9), F1
FCMPD F0, F1
BNE isNaN
MOVD $1, R0
MOVD R0, ret+0(FP)
RET
isNaN:
MOVD $0, ret+0(FP)
RET
// MVN: bitwise logical NOT
// This case simulates an application that modified R0-R30.
#define TWIDDLE_REGS() \
MVN R0, R0; \
MVN R1, R1; \
MVN R2, R2; \
MVN R3, R3; \
MVN R4, R4; \
MVN R5, R5; \
MVN R6, R6; \
MVN R7, R7; \
MVN R8, R8; \
MVN R9, R9; \
MVN R10, R10; \
MVN R11, R11; \
MVN R12, R12; \
MVN R13, R13; \
MVN R14, R14; \
MVN R15, R15; \
MVN R16, R16; \
MVN R17, R17; \
MVN R18_PLATFORM, R18_PLATFORM; \
MVN R19, R19; \
MVN R20, R20; \
MVN R21, R21; \
MVN R22, R22; \
MVN R23, R23; \
MVN R24, R24; \
MVN R25, R25; \
MVN R26, R26; \
MVN R27, R27; \
MVN g, g; \
MVN R29, R29; \
MVN R30, R30;
TEXT ·twiddleRegsSyscall(SB),NOSPLIT,$0
TWIDDLE_REGS()
MSR R10, TPIDR_EL0
// Trapped in el0_svc.
SVC
RET // never reached
TEXT ·AddrOfTwiddleRegsSyscall(SB),NOSPLIT,$0-8
MOVD $·twiddleRegsSyscall(SB), R0
MOVD R0, ret+0(FP)
RET
TEXT ·twiddleRegsFault(SB),NOSPLIT,$0
TWIDDLE_REGS()
MSR R10, TPIDR_EL0
// Trapped in el0_ia.
// Branch to Register branches unconditionally to an address in <Rn>.
JMP (R6) // <=> br x6, must fault
RET // never reached
TEXT ·AddrOfTwiddleRegsFault(SB),NOSPLIT,$0-8
MOVD $·twiddleRegsFault(SB), R0
MOVD R0, ret+0(FP)
RET
// pacLoop executes non-hint pointer authentication instructions
// (FEAT_PAuth) and then performs a syscall, in a loop. Unlike the
// HINT-space PAC instructions (e.g. PACIASP), the instructions below are
// UNDEFINED if pointer authentication is not available, and KVM injects
// an undefined instruction exception for them if pointer authentication
// is not enabled on the vCPU. They are encoded as raw words because the
// Go assembler does not support them.
TEXT ·pacLoop(SB),NOSPLIT,$0
start:
WORD $0xdac10020 // pacia x0, x1
WORD $0xdac11020 // autia x0, x1
WORD $0x9ac13002 // pacga x2, x0, x1
WORD $0xdac143e0 // xpaci x0
MOVD $SYS_GETPID, R8
SVC
B start
TEXT ·AddrOfPACLoop(SB),NOSPLIT,$0-8
MOVD $·pacLoop(SB), R0
MOVD R0, ret+0(FP)
RET