317 lines
5.4 KiB
ArmAsm
317 lines
5.4 KiB
ArmAsm
// SPDX-License-Identifier: GPL-2.0-only
|
|
// Copyright (C) 2021-2 ARM Limited.
|
|
// Original author: Mark Brown <broonie@kernel.org>
|
|
//
|
|
// Scalable Matrix Extension ZT context switch test
|
|
// Repeatedly writes unique test patterns into ZT0
|
|
// and reads them back to verify integrity.
|
|
|
|
#include <asm/unistd.h>
|
|
#include "assembler.h"
|
|
#include "asm-offsets.h"
|
|
#include "sme-inst.h"
|
|
|
|
.arch_extension sve
|
|
|
|
#define ZT_SZ 512
|
|
#define ZT_B (ZT_SZ / 8)
|
|
|
|
// Declare some storage space to shadow ZT register contents and a
|
|
// scratch buffer.
|
|
.pushsection .text
|
|
.data
|
|
.align 4
|
|
ztref:
|
|
.space ZT_B
|
|
scratch:
|
|
.space ZT_B
|
|
.popsection
|
|
|
|
|
|
// Generate a test pattern for storage in ZT
|
|
// x0: pid
|
|
// x1: generation
|
|
|
|
// These values are used to construct a 32-bit pattern that is repeated in the
|
|
// scratch buffer as many times as will fit:
|
|
// bits 31:24 generation number (increments once per test_loop)
|
|
// bits 23: 8 pid
|
|
// bits 7: 0 32-bit lane index
|
|
|
|
function pattern
|
|
mov w3, wzr
|
|
bfi w3, w0, #8, #16 // PID
|
|
bfi w3, w1, #24, #8 // Generation
|
|
|
|
ldr x0, =scratch
|
|
mov w1, #ZT_B / 4
|
|
|
|
0: str w3, [x0], #4
|
|
add w3, w3, #1 // Lane
|
|
subs w1, w1, #1
|
|
b.ne 0b
|
|
|
|
ret
|
|
endfunction
|
|
|
|
// Set up test pattern in a ZT horizontal vector
|
|
// x0: pid
|
|
// x1: generation
|
|
function setup_zt
|
|
mov x4, x30
|
|
|
|
bl pattern // Get pattern in scratch buffer
|
|
ldr x0, =ztref
|
|
ldr x1, =scratch
|
|
mov x2, #ZT_B
|
|
bl memcpy
|
|
|
|
ldr x0, =ztref
|
|
_ldr_zt 0 // load zt0 from pointer x0
|
|
|
|
ret x4
|
|
endfunction
|
|
|
|
// Trivial memory compare: compare x2 bytes starting at address x0 with
|
|
// bytes starting at address x1.
|
|
// Returns only if all bytes match; otherwise, the program is aborted.
|
|
// Clobbers x0-x5.
|
|
function memcmp
|
|
cbz x2, 2f
|
|
|
|
stp x0, x1, [sp, #-0x20]!
|
|
str x2, [sp, #0x10]
|
|
|
|
mov x5, #0
|
|
0: ldrb w3, [x0, x5]
|
|
ldrb w4, [x1, x5]
|
|
add x5, x5, #1
|
|
cmp w3, w4
|
|
b.ne 1f
|
|
subs x2, x2, #1
|
|
b.ne 0b
|
|
|
|
1: ldr x2, [sp, #0x10]
|
|
ldp x0, x1, [sp], #0x20
|
|
b.ne barf
|
|
|
|
2: ret
|
|
endfunction
|
|
|
|
// Verify that a ZT vector matches its shadow in memory, else abort
|
|
// Clobbers x0-x3
|
|
function check_zt
|
|
mov x3, x30
|
|
|
|
ldr x0, =scratch // Poison scratch
|
|
mov x1, #ZT_B
|
|
bl memfill_ae
|
|
|
|
ldr x0, =scratch
|
|
_str_zt 0
|
|
|
|
ldr x0, =ztref
|
|
ldr x1, =scratch
|
|
mov x2, #ZT_B
|
|
mov x30, x3
|
|
b memcmp
|
|
endfunction
|
|
|
|
// Any SME register modified here can cause corruption in the main
|
|
// thread -- but *only* the locations modified here.
|
|
function irritator_handler
|
|
// Increment the irritation signal count (x23):
|
|
ldr x0, [x2, #ucontext_regs + 8 * 23]
|
|
add x0, x0, #1
|
|
str x0, [x2, #ucontext_regs + 8 * 23]
|
|
|
|
// Corrupt some random ZT data
|
|
#if 0
|
|
adr x0, .text + (irritator_handler - .text) / 16 * 16
|
|
movi v0.8b, #1
|
|
movi v9.16b, #2
|
|
movi v31.8b, #3
|
|
#endif
|
|
|
|
ret
|
|
endfunction
|
|
|
|
function tickle_handler
|
|
// Increment the signal count (x23):
|
|
ldr x0, [x2, #ucontext_regs + 8 * 23]
|
|
add x0, x0, #1
|
|
str x0, [x2, #ucontext_regs + 8 * 23]
|
|
|
|
ret
|
|
endfunction
|
|
|
|
function terminate_handler
|
|
mov w21, w0
|
|
mov x20, x2
|
|
|
|
puts "Terminated by signal "
|
|
mov w0, w21
|
|
bl putdec
|
|
puts ", no error, iterations="
|
|
ldr x0, [x20, #ucontext_regs + 8 * 22]
|
|
bl putdec
|
|
puts ", signals="
|
|
ldr x0, [x20, #ucontext_regs + 8 * 23]
|
|
bl putdecn
|
|
|
|
mov x0, #0
|
|
mov x8, #__NR_exit
|
|
svc #0
|
|
endfunction
|
|
|
|
// w0: signal number
|
|
// x1: sa_action
|
|
// w2: sa_flags
|
|
// Clobbers x0-x6,x8
|
|
function setsignal
|
|
str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
|
|
|
|
mov w4, w0
|
|
mov x5, x1
|
|
mov w6, w2
|
|
|
|
add x0, sp, #16
|
|
mov x1, #sa_sz
|
|
bl memclr
|
|
|
|
mov w0, w4
|
|
add x1, sp, #16
|
|
str w6, [x1, #sa_flags]
|
|
str x5, [x1, #sa_handler]
|
|
mov x2, #0
|
|
mov x3, #sa_mask_sz
|
|
mov x8, #__NR_rt_sigaction
|
|
svc #0
|
|
|
|
cbz w0, 1f
|
|
|
|
puts "sigaction failure\n"
|
|
b .Labort
|
|
|
|
1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
|
|
ret
|
|
endfunction
|
|
|
|
// Main program entry point
|
|
.globl _start
|
|
function _start
|
|
mov x23, #0 // signal count
|
|
|
|
mov w0, #SIGINT
|
|
adr x1, terminate_handler
|
|
mov w2, #SA_SIGINFO
|
|
bl setsignal
|
|
|
|
mov w0, #SIGTERM
|
|
adr x1, terminate_handler
|
|
mov w2, #SA_SIGINFO
|
|
bl setsignal
|
|
|
|
mov w0, #SIGUSR1
|
|
adr x1, irritator_handler
|
|
mov w2, #SA_SIGINFO
|
|
orr w2, w2, #SA_NODEFER
|
|
bl setsignal
|
|
|
|
mov w0, #SIGUSR2
|
|
adr x1, tickle_handler
|
|
mov w2, #SA_SIGINFO
|
|
orr w2, w2, #SA_NODEFER
|
|
bl setsignal
|
|
|
|
smstart_za
|
|
|
|
// Obtain our PID, to ensure test pattern uniqueness between processes
|
|
mov x8, #__NR_getpid
|
|
svc #0
|
|
mov x20, x0
|
|
|
|
puts "PID:\t"
|
|
mov x0, x20
|
|
bl putdecn
|
|
|
|
mov x22, #0 // generation number, increments per iteration
|
|
.Ltest_loop:
|
|
mov x0, x20
|
|
mov x1, x22
|
|
bl setup_zt
|
|
|
|
mov x8, #__NR_sched_yield // Encourage preemption
|
|
svc #0
|
|
|
|
mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=1,SM=0
|
|
and x1, x0, #3
|
|
cmp x1, #2
|
|
b.ne svcr_barf
|
|
|
|
bl check_zt
|
|
|
|
add x22, x22, #1 // Everything still working
|
|
b .Ltest_loop
|
|
|
|
.Labort:
|
|
mov x0, #0
|
|
mov x1, #SIGABRT
|
|
mov x8, #__NR_kill
|
|
svc #0
|
|
endfunction
|
|
|
|
function barf
|
|
// fpsimd.c acitivty log dump hack
|
|
// ldr w0, =0xdeadc0de
|
|
// mov w8, #__NR_exit
|
|
// svc #0
|
|
// end hack
|
|
smstop
|
|
mov x10, x0 // expected data
|
|
mov x11, x1 // actual data
|
|
mov x12, x2 // data size
|
|
|
|
puts "Mismatch: PID="
|
|
mov x0, x20
|
|
bl putdec
|
|
puts ", iteration="
|
|
mov x0, x22
|
|
bl putdec
|
|
puts "\tExpected ["
|
|
mov x0, x10
|
|
mov x1, x12
|
|
bl dumphex
|
|
puts "]\n\tGot ["
|
|
mov x0, x11
|
|
mov x1, x12
|
|
bl dumphex
|
|
puts "]\n"
|
|
|
|
mov x8, #__NR_getpid
|
|
svc #0
|
|
// fpsimd.c acitivty log dump hack
|
|
// ldr w0, =0xdeadc0de
|
|
// mov w8, #__NR_exit
|
|
// svc #0
|
|
// ^ end of hack
|
|
mov x1, #SIGABRT
|
|
mov x8, #__NR_kill
|
|
svc #0
|
|
// mov x8, #__NR_exit
|
|
// mov x1, #1
|
|
// svc #0
|
|
endfunction
|
|
|
|
function svcr_barf
|
|
mov x10, x0
|
|
|
|
puts "Bad SVCR: "
|
|
mov x0, x10
|
|
bl putdecn
|
|
|
|
mov x8, #__NR_exit
|
|
mov x1, #1
|
|
svc #0
|
|
endfunction
|