1b2441318SGreg Kroah-Hartman// SPDX-License-Identifier: GPL-2.0 2474fd6e8SMartin Schwidefsky/* 3474fd6e8SMartin Schwidefsky * raid6_vx$#.c 4474fd6e8SMartin Schwidefsky * 5474fd6e8SMartin Schwidefsky * $#-way unrolled RAID6 gen/xor functions for s390 6474fd6e8SMartin Schwidefsky * based on the vector facility 7474fd6e8SMartin Schwidefsky * 8474fd6e8SMartin Schwidefsky * Copyright IBM Corp. 2016 9474fd6e8SMartin Schwidefsky * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 10474fd6e8SMartin Schwidefsky * 11474fd6e8SMartin Schwidefsky * This file is postprocessed using unroll.awk. 12474fd6e8SMartin Schwidefsky */ 13474fd6e8SMartin Schwidefsky 14474fd6e8SMartin Schwidefsky#include <linux/raid/pq.h> 15474fd6e8SMartin Schwidefsky#include <asm/fpu/api.h> 16*706f2adaSHeiko Carstens#include <asm/vx-insn.h> 17474fd6e8SMartin Schwidefsky 18474fd6e8SMartin Schwidefsky#define NSIZE 16 19474fd6e8SMartin Schwidefsky 20474fd6e8SMartin Schwidefskystatic inline void LOAD_CONST(void) 21474fd6e8SMartin Schwidefsky{ 22474fd6e8SMartin Schwidefsky asm volatile("VREPIB %v24,7"); 23474fd6e8SMartin Schwidefsky asm volatile("VREPIB %v25,0x1d"); 24474fd6e8SMartin Schwidefsky} 25474fd6e8SMartin Schwidefsky 26474fd6e8SMartin Schwidefsky/* 27474fd6e8SMartin Schwidefsky * The SHLBYTE() operation shifts each of the 16 bytes in 28474fd6e8SMartin Schwidefsky * vector register y left by 1 bit and stores the result in 29474fd6e8SMartin Schwidefsky * vector register x. 30474fd6e8SMartin Schwidefsky */ 31474fd6e8SMartin Schwidefskystatic inline void SHLBYTE(int x, int y) 32474fd6e8SMartin Schwidefsky{ 33474fd6e8SMartin Schwidefsky asm volatile ("VAB %0,%1,%1" : : "i" (x), "i" (y)); 34474fd6e8SMartin Schwidefsky} 35474fd6e8SMartin Schwidefsky 36474fd6e8SMartin Schwidefsky/* 37474fd6e8SMartin Schwidefsky * For each of the 16 bytes in the vector register y the MASK() 38474fd6e8SMartin Schwidefsky * operation returns 0xFF if the high bit of the byte is 1, 39474fd6e8SMartin Schwidefsky * or 0x00 if the high bit is 0. The result is stored in vector 40474fd6e8SMartin Schwidefsky * register x. 41474fd6e8SMartin Schwidefsky */ 42474fd6e8SMartin Schwidefskystatic inline void MASK(int x, int y) 43474fd6e8SMartin Schwidefsky{ 44474fd6e8SMartin Schwidefsky asm volatile ("VESRAVB %0,%1,24" : : "i" (x), "i" (y)); 45474fd6e8SMartin Schwidefsky} 46474fd6e8SMartin Schwidefsky 47474fd6e8SMartin Schwidefskystatic inline void AND(int x, int y, int z) 48474fd6e8SMartin Schwidefsky{ 49474fd6e8SMartin Schwidefsky asm volatile ("VN %0,%1,%2" : : "i" (x), "i" (y), "i" (z)); 50474fd6e8SMartin Schwidefsky} 51474fd6e8SMartin Schwidefsky 52474fd6e8SMartin Schwidefskystatic inline void XOR(int x, int y, int z) 53474fd6e8SMartin Schwidefsky{ 54474fd6e8SMartin Schwidefsky asm volatile ("VX %0,%1,%2" : : "i" (x), "i" (y), "i" (z)); 55474fd6e8SMartin Schwidefsky} 56474fd6e8SMartin Schwidefsky 57ad5728ceSKees Cookstatic inline void LOAD_DATA(int x, u8 *ptr) 58474fd6e8SMartin Schwidefsky{ 59ad5728ceSKees Cook typedef struct { u8 _[16 * $#]; } addrtype; 60474fd6e8SMartin Schwidefsky register addrtype *__ptr asm("1") = (addrtype *) ptr; 61474fd6e8SMartin Schwidefsky 62eec0a43dSVasily Gorbik asm volatile ("VLM %2,%3,0,%1" 63ad5728ceSKees Cook : : "m" (*__ptr), "a" (__ptr), "i" (x), 64ad5728ceSKees Cook "i" (x + $# - 1)); 65474fd6e8SMartin Schwidefsky} 66474fd6e8SMartin Schwidefsky 67ad5728ceSKees Cookstatic inline void STORE_DATA(int x, u8 *ptr) 68474fd6e8SMartin Schwidefsky{ 69ad5728ceSKees Cook typedef struct { u8 _[16 * $#]; } addrtype; 70474fd6e8SMartin Schwidefsky register addrtype *__ptr asm("1") = (addrtype *) ptr; 71474fd6e8SMartin Schwidefsky 72474fd6e8SMartin Schwidefsky asm volatile ("VSTM %2,%3,0,1" 73ad5728ceSKees Cook : "=m" (*__ptr) : "a" (__ptr), "i" (x), 74ad5728ceSKees Cook "i" (x + $# - 1)); 75474fd6e8SMartin Schwidefsky} 76474fd6e8SMartin Schwidefsky 77474fd6e8SMartin Schwidefskystatic inline void COPY_VEC(int x, int y) 78474fd6e8SMartin Schwidefsky{ 79474fd6e8SMartin Schwidefsky asm volatile ("VLR %0,%1" : : "i" (x), "i" (y)); 80474fd6e8SMartin Schwidefsky} 81474fd6e8SMartin Schwidefsky 82474fd6e8SMartin Schwidefskystatic void raid6_s390vx$#_gen_syndrome(int disks, size_t bytes, void **ptrs) 83474fd6e8SMartin Schwidefsky{ 84474fd6e8SMartin Schwidefsky struct kernel_fpu vxstate; 85474fd6e8SMartin Schwidefsky u8 **dptr, *p, *q; 86474fd6e8SMartin Schwidefsky int d, z, z0; 87474fd6e8SMartin Schwidefsky 88474fd6e8SMartin Schwidefsky kernel_fpu_begin(&vxstate, KERNEL_VXR); 89474fd6e8SMartin Schwidefsky LOAD_CONST(); 90474fd6e8SMartin Schwidefsky 91474fd6e8SMartin Schwidefsky dptr = (u8 **) ptrs; 92474fd6e8SMartin Schwidefsky z0 = disks - 3; /* Highest data disk */ 93474fd6e8SMartin Schwidefsky p = dptr[z0 + 1]; /* XOR parity */ 94474fd6e8SMartin Schwidefsky q = dptr[z0 + 2]; /* RS syndrome */ 95474fd6e8SMartin Schwidefsky 96474fd6e8SMartin Schwidefsky for (d = 0; d < bytes; d += $#*NSIZE) { 97ad5728ceSKees Cook LOAD_DATA(0,&dptr[z0][d]); 98474fd6e8SMartin Schwidefsky COPY_VEC(8+$$,0+$$); 99474fd6e8SMartin Schwidefsky for (z = z0 - 1; z >= 0; z--) { 100474fd6e8SMartin Schwidefsky MASK(16+$$,8+$$); 101474fd6e8SMartin Schwidefsky AND(16+$$,16+$$,25); 102474fd6e8SMartin Schwidefsky SHLBYTE(8+$$,8+$$); 103474fd6e8SMartin Schwidefsky XOR(8+$$,8+$$,16+$$); 104ad5728ceSKees Cook LOAD_DATA(16,&dptr[z][d]); 105474fd6e8SMartin Schwidefsky XOR(0+$$,0+$$,16+$$); 106474fd6e8SMartin Schwidefsky XOR(8+$$,8+$$,16+$$); 107474fd6e8SMartin Schwidefsky } 108ad5728ceSKees Cook STORE_DATA(0,&p[d]); 109ad5728ceSKees Cook STORE_DATA(8,&q[d]); 110474fd6e8SMartin Schwidefsky } 111474fd6e8SMartin Schwidefsky kernel_fpu_end(&vxstate, KERNEL_VXR); 112474fd6e8SMartin Schwidefsky} 113474fd6e8SMartin Schwidefsky 114474fd6e8SMartin Schwidefskystatic void raid6_s390vx$#_xor_syndrome(int disks, int start, int stop, 115474fd6e8SMartin Schwidefsky size_t bytes, void **ptrs) 116474fd6e8SMartin Schwidefsky{ 117474fd6e8SMartin Schwidefsky struct kernel_fpu vxstate; 118474fd6e8SMartin Schwidefsky u8 **dptr, *p, *q; 119474fd6e8SMartin Schwidefsky int d, z, z0; 120474fd6e8SMartin Schwidefsky 121474fd6e8SMartin Schwidefsky dptr = (u8 **) ptrs; 122474fd6e8SMartin Schwidefsky z0 = stop; /* P/Q right side optimization */ 123474fd6e8SMartin Schwidefsky p = dptr[disks - 2]; /* XOR parity */ 124474fd6e8SMartin Schwidefsky q = dptr[disks - 1]; /* RS syndrome */ 125474fd6e8SMartin Schwidefsky 126474fd6e8SMartin Schwidefsky kernel_fpu_begin(&vxstate, KERNEL_VXR); 127474fd6e8SMartin Schwidefsky LOAD_CONST(); 128474fd6e8SMartin Schwidefsky 129474fd6e8SMartin Schwidefsky for (d = 0; d < bytes; d += $#*NSIZE) { 130474fd6e8SMartin Schwidefsky /* P/Q data pages */ 131ad5728ceSKees Cook LOAD_DATA(0,&dptr[z0][d]); 132474fd6e8SMartin Schwidefsky COPY_VEC(8+$$,0+$$); 133474fd6e8SMartin Schwidefsky for (z = z0 - 1; z >= start; z--) { 134474fd6e8SMartin Schwidefsky MASK(16+$$,8+$$); 135474fd6e8SMartin Schwidefsky AND(16+$$,16+$$,25); 136474fd6e8SMartin Schwidefsky SHLBYTE(8+$$,8+$$); 137474fd6e8SMartin Schwidefsky XOR(8+$$,8+$$,16+$$); 138ad5728ceSKees Cook LOAD_DATA(16,&dptr[z][d]); 139474fd6e8SMartin Schwidefsky XOR(0+$$,0+$$,16+$$); 140474fd6e8SMartin Schwidefsky XOR(8+$$,8+$$,16+$$); 141474fd6e8SMartin Schwidefsky } 142474fd6e8SMartin Schwidefsky /* P/Q left side optimization */ 143474fd6e8SMartin Schwidefsky for (z = start - 1; z >= 0; z--) { 144474fd6e8SMartin Schwidefsky MASK(16+$$,8+$$); 145474fd6e8SMartin Schwidefsky AND(16+$$,16+$$,25); 146474fd6e8SMartin Schwidefsky SHLBYTE(8+$$,8+$$); 147474fd6e8SMartin Schwidefsky XOR(8+$$,8+$$,16+$$); 148474fd6e8SMartin Schwidefsky } 149ad5728ceSKees Cook LOAD_DATA(16,&p[d]); 150474fd6e8SMartin Schwidefsky XOR(16+$$,16+$$,0+$$); 151ad5728ceSKees Cook STORE_DATA(16,&p[d]); 152ad5728ceSKees Cook LOAD_DATA(16,&q[d]); 153474fd6e8SMartin Schwidefsky XOR(16+$$,16+$$,8+$$); 154ad5728ceSKees Cook STORE_DATA(16,&q[d]); 155474fd6e8SMartin Schwidefsky } 156474fd6e8SMartin Schwidefsky kernel_fpu_end(&vxstate, KERNEL_VXR); 157474fd6e8SMartin Schwidefsky} 158474fd6e8SMartin Schwidefsky 159474fd6e8SMartin Schwidefskystatic int raid6_s390vx$#_valid(void) 160474fd6e8SMartin Schwidefsky{ 161474fd6e8SMartin Schwidefsky return MACHINE_HAS_VX; 162474fd6e8SMartin Schwidefsky} 163474fd6e8SMartin Schwidefsky 164474fd6e8SMartin Schwidefskyconst struct raid6_calls raid6_s390vx$# = { 165474fd6e8SMartin Schwidefsky raid6_s390vx$#_gen_syndrome, 166474fd6e8SMartin Schwidefsky raid6_s390vx$#_xor_syndrome, 167474fd6e8SMartin Schwidefsky raid6_s390vx$#_valid, 168474fd6e8SMartin Schwidefsky "vx128x$#", 169474fd6e8SMartin Schwidefsky 1 170474fd6e8SMartin Schwidefsky}; 171