Path: blob/master/tools/testing/selftests/arm64/fp/sve-test.S
26289 views
// SPDX-License-Identifier: GPL-2.0-only1// Copyright (C) 2015-2019 ARM Limited.2// Original author: Dave Martin <Dave.Martin@arm.com>3//4// Simple Scalable Vector Extension context switch test5// Repeatedly writes unique test patterns into each SVE register6// and reads them back to verify integrity.7//8// for x in `seq 1 NR_CPUS`; do sve-test & pids=$pids\ $! ; done9// (leave it running for as long as you want...)10// kill $pids1112#include <asm/unistd.h>13#include "assembler.h"14#include "asm-offsets.h"15#include "sme-inst.h"1617#define NZR 3218#define NPR 1619#define MAXVL_B (2048 / 8)2021.arch_extension sve2223.macro _sve_ldr_v zt, xn24ldr z\zt, [x\xn]25.endm2627.macro _sve_str_v zt, xn28str z\zt, [x\xn]29.endm3031.macro _sve_ldr_p pt, xn32ldr p\pt, [x\xn]33.endm3435.macro _sve_str_p pt, xn36str p\pt, [x\xn]37.endm3839// Generate accessor functions to read/write programmatically selected40// SVE registers.41// x0 is the register index to access42// x1 is the memory address to read from (getz,setp) or store to (setz,setp)43// All clobber x0-x244define_accessor setz, NZR, _sve_ldr_v45define_accessor getz, NZR, _sve_str_v46define_accessor setp, NPR, _sve_ldr_p47define_accessor getp, NPR, _sve_str_p4849// Declare some storate space to shadow the SVE register contents:50.pushsection .text51.data52.align 453zref:54.space MAXVL_B * NZR55pref:56.space MAXVL_B / 8 * NPR57ffrref:58.space MAXVL_B / 859scratch:60.space MAXVL_B61.popsection6263// Generate a test pattern for storage in SVE registers64// x0: pid (16 bits)65// x1: register number (6 bits)66// x2: generation (4 bits)6768// These values are used to constuct a 32-bit pattern that is repeated in the69// scratch buffer as many times as will fit:70// bits 31:28 generation number (increments once per test_loop)71// bits 27:22 32-bit lane index72// bits 21:16 register number73// bits 15: 0 pid7475function pattern76orr w1, w0, w1, lsl #1677orr w2, w1, w2, lsl #287879ldr x0, =scratch80mov w1, #MAXVL_B / 481820: str w2, [x0], #483add w2, w2, #(1 << 22)84subs w1, w1, #185bne 0b8687ret88endfunction8990// Get the address of shadow data for SVE Z-register Z<xn>91.macro _adrz xd, xn, nrtmp92ldr \xd, =zref93rdvl x\nrtmp, #194madd \xd, x\nrtmp, \xn, \xd95.endm9697// Get the address of shadow data for SVE P-register P<xn - NZR>98.macro _adrp xd, xn, nrtmp99ldr \xd, =pref100rdvl x\nrtmp, #1101lsr x\nrtmp, x\nrtmp, #3102sub \xn, \xn, #NZR103madd \xd, x\nrtmp, \xn, \xd104.endm105106// Set up test pattern in a SVE Z-register107// x0: pid108// x1: register number109// x2: generation110function setup_zreg111mov x4, x30112113mov x6, x1114bl pattern115_adrz x0, x6, 2116mov x5, x0117ldr x1, =scratch118bl memcpy119120mov x0, x6121mov x1, x5122bl setz123124ret x4125endfunction126127// Set up test pattern in a SVE P-register128// x0: pid129// x1: register number130// x2: generation131function setup_preg132mov x4, x30133134mov x6, x1135bl pattern136_adrp x0, x6, 2137mov x5, x0138ldr x1, =scratch139bl memcpy140141mov x0, x6142mov x1, x5143bl setp144145ret x4146endfunction147148// Set up test pattern in the FFR149// x0: pid150// x2: generation151//152// We need to generate a canonical FFR value, which consists of a number of153// low "1" bits, followed by a number of zeros. This gives us 17 unique values154// per 16 bits of FFR, so we create a 4 bit signature out of the PID and155// generation, and use that as the initial number of ones in the pattern.156// We fill the upper lanes of FFR with zeros.157// Beware: corrupts P0.158function setup_ffr159#ifndef SSVE160mov x4, x30161162and w0, w0, #0x3163bfi w0, w2, #2, #2164mov w1, #1165lsl w1, w1, w0166sub w1, w1, #1167168ldr x0, =ffrref169strh w1, [x0], 2170rdvl x1, #1171lsr x1, x1, #3172sub x1, x1, #2173bl memclr174175mov x0, #0176ldr x1, =ffrref177bl setp178179wrffr p0.b180181ret x4182#else183ret184#endif185endfunction186187// Trivial memory compare: compare x2 bytes starting at address x0 with188// bytes starting at address x1.189// Returns only if all bytes match; otherwise, the program is aborted.190// Clobbers x0-x5.191function memcmp192cbz x2, 2f193194stp x0, x1, [sp, #-0x20]!195str x2, [sp, #0x10]196197mov x5, #01980: ldrb w3, [x0, x5]199ldrb w4, [x1, x5]200add x5, x5, #1201cmp w3, w4202b.ne 1f203subs x2, x2, #1204b.ne 0b2052061: ldr x2, [sp, #0x10]207ldp x0, x1, [sp], #0x20208b.ne barf2092102: ret211endfunction212213// Verify that a SVE Z-register matches its shadow in memory, else abort214// x0: reg number215// Clobbers x0-x7.216function check_zreg217mov x3, x30218219_adrz x5, x0, 6220mov x4, x0221ldr x7, =scratch222223mov x0, x7224mov x1, x6225bl memfill_ae226227mov x0, x4228mov x1, x7229bl getz230231mov x0, x5232mov x1, x7233mov x2, x6234mov x30, x3235b memcmp236endfunction237238// Verify that a SVE P-register matches its shadow in memory, else abort239// x0: reg number240// Clobbers x0-x7.241function check_preg242mov x3, x30243244_adrp x5, x0, 6245mov x4, x0246ldr x7, =scratch247248mov x0, x7249mov x1, x6250bl memfill_ae251252mov x0, x4253mov x1, x7254bl getp255256mov x0, x5257mov x1, x7258mov x2, x6259mov x30, x3260b memcmp261endfunction262263// Verify that the FFR matches its shadow in memory, else abort264// Beware -- corrupts P0.265// Clobbers x0-x5.266function check_ffr267#ifndef SSVE268mov x3, x30269270ldr x4, =scratch271rdvl x5, #1272lsr x5, x5, #3273274mov x0, x4275mov x1, x5276bl memfill_ae277278rdffr p0.b279mov x0, #0280mov x1, x4281bl getp282283ldr x0, =ffrref284mov x1, x4285mov x2, x5286mov x30, x3287b memcmp288#else289ret290#endif291endfunction292293// Modify live register state, the signal return will undo our changes294function irritator_handler295// Increment the irritation signal count (x23):296ldr x0, [x2, #ucontext_regs + 8 * 23]297add x0, x0, #1298str x0, [x2, #ucontext_regs + 8 * 23]299300// Corrupt some random Z-regs301movi v0.8b, #1302movi v9.16b, #2303movi v31.8b, #3304// And P0305ptrue p0.d306#ifndef SSVE307// And FFR308wrffr p15.b309#endif310311ret312endfunction313314function tickle_handler315// Increment the signal count (x23):316ldr x0, [x2, #ucontext_regs + 8 * 23]317add x0, x0, #1318str x0, [x2, #ucontext_regs + 8 * 23]319320ret321endfunction322323function terminate_handler324mov w21, w0325mov x20, x2326327puts "Terminated by signal "328mov w0, w21329bl putdec330puts ", no error, iterations="331ldr x0, [x20, #ucontext_regs + 8 * 22]332bl putdec333puts ", signals="334ldr x0, [x20, #ucontext_regs + 8 * 23]335bl putdecn336337mov x0, #0338mov x8, #__NR_exit339svc #0340endfunction341342// w0: signal number343// x1: sa_action344// w2: sa_flags345// Clobbers x0-x6,x8346function setsignal347str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!348349mov w4, w0350mov x5, x1351mov w6, w2352353add x0, sp, #16354mov x1, #sa_sz355bl memclr356357mov w0, w4358add x1, sp, #16359str w6, [x1, #sa_flags]360str x5, [x1, #sa_handler]361mov x2, #0362mov x3, #sa_mask_sz363mov x8, #__NR_rt_sigaction364svc #0365366cbz w0, 1f367368puts "sigaction failure\n"369b .Labort3703711: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)372ret373endfunction374375// Main program entry point376.globl _start377function _start378enable_gcs379380mov x23, #0 // Irritation signal count381382mov w0, #SIGINT383adr x1, terminate_handler384mov w2, #SA_SIGINFO385bl setsignal386387mov w0, #SIGTERM388adr x1, terminate_handler389mov w2, #SA_SIGINFO390bl setsignal391392mov w0, #SIGUSR1393adr x1, irritator_handler394mov w2, #SA_SIGINFO395orr w2, w2, #SA_NODEFER396bl setsignal397398mov w0, #SIGUSR2399adr x1, tickle_handler400mov w2, #SA_SIGINFO401orr w2, w2, #SA_NODEFER402bl setsignal403404#ifdef SSVE405puts "Streaming mode "406smstart_sm407#endif408409// Sanity-check and report the vector length410411rdvl x19, #8412cmp x19, #128413b.lo 1f414cmp x19, #2048415b.hi 1f416tst x19, #(8 - 1)417b.eq 2f4184191: puts "Bad vector length: "420mov x0, x19421bl putdecn422b .Labort4234242: puts "Vector length:\t"425mov x0, x19426bl putdec427puts " bits\n"428429// Obtain our PID, to ensure test pattern uniqueness between processes430431mov x8, #__NR_getpid432svc #0433mov x20, x0434435puts "PID:\t"436mov x0, x20437bl putdecn438439#ifdef SSVE440smstart_sm // syscalls will have exited streaming mode441#endif442443mov x22, #0 // generation number, increments per iteration444.Ltest_loop:445rdvl x0, #8446cmp x0, x19447b.ne vl_barf448449mov x21, #0 // Set up Z-regs & shadow with test pattern4500: mov x0, x20451mov x1, x21452and x2, x22, #0xf453bl setup_zreg454add x21, x21, #1455cmp x21, #NZR456b.lo 0b457458mov x0, x20 // Set up FFR & shadow with test pattern459mov x1, #NZR + NPR460and x2, x22, #0xf461bl setup_ffr4624630: mov x0, x20 // Set up P-regs & shadow with test pattern464mov x1, x21465and x2, x22, #0xf466bl setup_preg467add x21, x21, #1468cmp x21, #NZR + NPR469b.lo 0b470471// Can't do this when SVE state is volatile across SVC:472// mov x8, #__NR_sched_yield // Encourage preemption473// svc #0474475#ifdef SSVE476mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=0,SM=1477and x1, x0, #3478cmp x1, #1479b.ne svcr_barf480#endif481482mov x21, #04830: mov x0, x21484bl check_zreg485add x21, x21, #1486cmp x21, #NZR487b.lo 0b4884890: mov x0, x21490bl check_preg491add x21, x21, #1492cmp x21, #NZR + NPR493b.lo 0b494495bl check_ffr496497add x22, x22, #1498b .Ltest_loop499500.Labort:501mov x0, #0502mov x1, #SIGABRT503mov x8, #__NR_kill504svc #0505endfunction506507function barf508// fpsimd.c acitivty log dump hack509// ldr w0, =0xdeadc0de510// mov w8, #__NR_exit511// svc #0512// end hack513mov x10, x0 // expected data514mov x11, x1 // actual data515mov x12, x2 // data size516517#ifdef SSVE518mrs x13, S3_3_C4_C2_2519#endif520521puts "Mismatch: PID="522mov x0, x20523bl putdec524puts ", iteration="525mov x0, x22526bl putdec527puts ", reg="528mov x0, x21529bl putdecn530puts "\tExpected ["531mov x0, x10532mov x1, x12533bl dumphex534puts "]\n\tGot ["535mov x0, x11536mov x1, x12537bl dumphex538puts "]\n"539540#ifdef SSVE541puts "\tSVCR: "542mov x0, x13543bl putdecn544#endif545546mov x8, #__NR_getpid547svc #0548// fpsimd.c acitivty log dump hack549// ldr w0, =0xdeadc0de550// mov w8, #__NR_exit551// svc #0552// ^ end of hack553mov x1, #SIGABRT554mov x8, #__NR_kill555svc #0556// mov x8, #__NR_exit557// mov x1, #1558// svc #0559endfunction560561function vl_barf562mov x10, x0563564puts "Bad active VL: "565mov x0, x10566bl putdecn567568mov x8, #__NR_exit569mov x1, #1570svc #0571endfunction572573function svcr_barf574mov x10, x0575576puts "Bad SVCR: "577mov x0, x10578bl putdecn579580mov x8, #__NR_exit581mov x1, #1582svc #0583endfunction584585586