1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 253631b54SCatalin Marinas/* 353631b54SCatalin Marinas * FP/SIMD state saving and restoring 453631b54SCatalin Marinas * 553631b54SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 653631b54SCatalin Marinas * Author: Catalin Marinas <catalin.marinas@arm.com> 753631b54SCatalin Marinas */ 853631b54SCatalin Marinas 953631b54SCatalin Marinas#include <linux/linkage.h> 1053631b54SCatalin Marinas 1153631b54SCatalin Marinas#include <asm/assembler.h> 12cfc5180eSMarc Zyngier#include <asm/fpsimdmacros.h> 1353631b54SCatalin Marinas 1453631b54SCatalin Marinas/* 1553631b54SCatalin Marinas * Save the FP registers. 1653631b54SCatalin Marinas * 1753631b54SCatalin Marinas * x0 - pointer to struct fpsimd_state 1853631b54SCatalin Marinas */ 190343a7e4SMark BrownSYM_FUNC_START(fpsimd_save_state) 20cfc5180eSMarc Zyngier fpsimd_save x0, 8 2153631b54SCatalin Marinas ret 220343a7e4SMark BrownSYM_FUNC_END(fpsimd_save_state) 2353631b54SCatalin Marinas 2453631b54SCatalin Marinas/* 2553631b54SCatalin Marinas * Load the FP registers. 2653631b54SCatalin Marinas * 2753631b54SCatalin Marinas * x0 - pointer to struct fpsimd_state 2853631b54SCatalin Marinas */ 290343a7e4SMark BrownSYM_FUNC_START(fpsimd_load_state) 30cfc5180eSMarc Zyngier fpsimd_restore x0, 8 3153631b54SCatalin Marinas ret 320343a7e4SMark BrownSYM_FUNC_END(fpsimd_load_state) 331fc5dce7SDave Martin 341fc5dce7SDave Martin#ifdef CONFIG_ARM64_SVE 351e530f13SJulien Grall 3638ee3c5eSMark Brown/* 3738ee3c5eSMark Brown * Save the SVE state 3838ee3c5eSMark Brown * 3938ee3c5eSMark Brown * x0 - pointer to buffer for state 4038ee3c5eSMark Brown * x1 - pointer to storage for FPSR 419f584866SMark Brown * x2 - Save FFR if non-zero 4238ee3c5eSMark Brown */ 430343a7e4SMark BrownSYM_FUNC_START(sve_save_state) 449f584866SMark Brown sve_save 0, x1, x2, 3 451fc5dce7SDave Martin ret 460343a7e4SMark BrownSYM_FUNC_END(sve_save_state) 471fc5dce7SDave Martin 4838ee3c5eSMark Brown/* 4938ee3c5eSMark Brown * Load the SVE state 5038ee3c5eSMark Brown * 5138ee3c5eSMark Brown * x0 - pointer to buffer for state 5238ee3c5eSMark Brown * x1 - pointer to storage for FPSR 539f584866SMark Brown * x2 - Restore FFR if non-zero 5438ee3c5eSMark Brown */ 550343a7e4SMark BrownSYM_FUNC_START(sve_load_state) 56ddc806b5SMark Brown sve_load 0, x1, x2, 4 571fc5dce7SDave Martin ret 580343a7e4SMark BrownSYM_FUNC_END(sve_load_state) 591fc5dce7SDave Martin 600343a7e4SMark BrownSYM_FUNC_START(sve_get_vl) 611fc5dce7SDave Martin _sve_rdvl 0, 1 621fc5dce7SDave Martin ret 630343a7e4SMark BrownSYM_FUNC_END(sve_get_vl) 641e530f13SJulien Grall 65cccb78ceSMark BrownSYM_FUNC_START(sve_set_vq) 66cccb78ceSMark Brown sve_load_vq x0, x1, x2 67cccb78ceSMark Brown ret 68cccb78ceSMark BrownSYM_FUNC_END(sve_set_vq) 69cccb78ceSMark Brown 709c4b4c70SJulien Grall/* 71ad4711f9SMark Brown * Zero all SVE registers but the first 128-bits of each vector 72ad4711f9SMark Brown * 73ad4711f9SMark Brown * VQ must already be configured by caller, any further updates of VQ 74ad4711f9SMark Brown * will need to ensure that the register state remains valid. 75ad4711f9SMark Brown * 769f584866SMark Brown * x0 = include FFR? 779f584866SMark Brown * x1 = VQ - 1 78ad4711f9SMark Brown */ 791e530f13SJulien GrallSYM_FUNC_START(sve_flush_live) 809f584866SMark Brown cbz x1, 1f // A VQ-1 of 0 is 128 bits so no extra Z state 81483dbf6aSMark Brown sve_flush_z 829f584866SMark Brown1: sve_flush_p 839f584866SMark Brown tbz x0, #0, 2f 849f584866SMark Brown sve_flush_ffr 859f584866SMark Brown2: ret 861e530f13SJulien GrallSYM_FUNC_END(sve_flush_live) 871e530f13SJulien Grall 881fc5dce7SDave Martin#endif /* CONFIG_ARM64_SVE */ 89b42990d3SMark Brown 90b42990d3SMark Brown#ifdef CONFIG_ARM64_SME 91b42990d3SMark Brown 92b42990d3SMark BrownSYM_FUNC_START(sme_get_vl) 93b42990d3SMark Brown _sme_rdsvl 0, 1 94b42990d3SMark Brown ret 95b42990d3SMark BrownSYM_FUNC_END(sme_get_vl) 96b42990d3SMark Brown 97af7167d6SMark BrownSYM_FUNC_START(sme_set_vq) 98af7167d6SMark Brown sme_load_vq x0, x1, x2 99af7167d6SMark Brown ret 100af7167d6SMark BrownSYM_FUNC_END(sme_set_vq) 101af7167d6SMark Brown 1020033cd93SMark Brown/* 103*95fcec71SMark Brown * Save the ZA and ZT state 1040033cd93SMark Brown * 1050033cd93SMark Brown * x0 - pointer to buffer for state 106*95fcec71SMark Brown * x1 - number of ZT registers to save 1070033cd93SMark Brown */ 108*95fcec71SMark BrownSYM_FUNC_START(sme_save_state) 109*95fcec71SMark Brown _sme_rdsvl 2, 1 // x2 = VL/8 110*95fcec71SMark Brown sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA 111*95fcec71SMark Brown 112*95fcec71SMark Brown cbz x1, 1f 113*95fcec71SMark Brown _str_zt 0 114*95fcec71SMark Brown1: 1150033cd93SMark Brown ret 116*95fcec71SMark BrownSYM_FUNC_END(sme_save_state) 1170033cd93SMark Brown 1180033cd93SMark Brown/* 119*95fcec71SMark Brown * Load the ZA and ZT state 1200033cd93SMark Brown * 1210033cd93SMark Brown * x0 - pointer to buffer for state 122*95fcec71SMark Brown * x1 - number of ZT registers to save 1230033cd93SMark Brown */ 124*95fcec71SMark BrownSYM_FUNC_START(sme_load_state) 125*95fcec71SMark Brown _sme_rdsvl 2, 1 // x2 = VL/8 126*95fcec71SMark Brown sme_load_za 0, x2, 12 // Leaves x0 pointing to the end of ZA 127*95fcec71SMark Brown 128*95fcec71SMark Brown cbz x1, 1f 129*95fcec71SMark Brown _ldr_zt 0 130*95fcec71SMark Brown1: 1310033cd93SMark Brown ret 132*95fcec71SMark BrownSYM_FUNC_END(sme_load_state) 1330033cd93SMark Brown 134b42990d3SMark Brown#endif /* CONFIG_ARM64_SME */ 135