cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

recov_s390xc.c (2774B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * RAID-6 data recovery in dual failure mode based on the XC instruction.
      4 *
      5 * Copyright IBM Corp. 2016
      6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
      7 */
      8
      9#include <linux/export.h>
     10#include <linux/raid/pq.h>
     11
     12static inline void xor_block(u8 *p1, u8 *p2)
     13{
     14	typedef struct { u8 _[256]; } addrtype;
     15
     16	asm volatile(
     17		"	xc	0(256,%[p1]),0(%[p2])\n"
     18		: "+m" (*(addrtype *) p1) : "m" (*(addrtype *) p2),
     19		  [p1] "a" (p1), [p2] "a" (p2) : "cc");
     20}
     21
     22/* Recover two failed data blocks. */
     23static void raid6_2data_recov_s390xc(int disks, size_t bytes, int faila,
     24		int failb, void **ptrs)
     25{
     26	u8 *p, *q, *dp, *dq;
     27	const u8 *pbmul;	/* P multiplier table for B data */
     28	const u8 *qmul;		/* Q multiplier table (for both) */
     29	int i;
     30
     31	p = (u8 *)ptrs[disks-2];
     32	q = (u8 *)ptrs[disks-1];
     33
     34	/* Compute syndrome with zero for the missing data pages
     35	   Use the dead data pages as temporary storage for
     36	   delta p and delta q */
     37	dp = (u8 *)ptrs[faila];
     38	ptrs[faila] = (void *)raid6_empty_zero_page;
     39	ptrs[disks-2] = dp;
     40	dq = (u8 *)ptrs[failb];
     41	ptrs[failb] = (void *)raid6_empty_zero_page;
     42	ptrs[disks-1] = dq;
     43
     44	raid6_call.gen_syndrome(disks, bytes, ptrs);
     45
     46	/* Restore pointer table */
     47	ptrs[faila]   = dp;
     48	ptrs[failb]   = dq;
     49	ptrs[disks-2] = p;
     50	ptrs[disks-1] = q;
     51
     52	/* Now, pick the proper data tables */
     53	pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
     54	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
     55
     56	/* Now do it... */
     57	while (bytes) {
     58		xor_block(dp, p);
     59		xor_block(dq, q);
     60		for (i = 0; i < 256; i++)
     61			dq[i] = pbmul[dp[i]] ^ qmul[dq[i]];
     62		xor_block(dp, dq);
     63		p += 256;
     64		q += 256;
     65		dp += 256;
     66		dq += 256;
     67		bytes -= 256;
     68	}
     69}
     70
     71/* Recover failure of one data block plus the P block */
     72static void raid6_datap_recov_s390xc(int disks, size_t bytes, int faila,
     73		void **ptrs)
     74{
     75	u8 *p, *q, *dq;
     76	const u8 *qmul;		/* Q multiplier table */
     77	int i;
     78
     79	p = (u8 *)ptrs[disks-2];
     80	q = (u8 *)ptrs[disks-1];
     81
     82	/* Compute syndrome with zero for the missing data page
     83	   Use the dead data page as temporary storage for delta q */
     84	dq = (u8 *)ptrs[faila];
     85	ptrs[faila] = (void *)raid6_empty_zero_page;
     86	ptrs[disks-1] = dq;
     87
     88	raid6_call.gen_syndrome(disks, bytes, ptrs);
     89
     90	/* Restore pointer table */
     91	ptrs[faila]   = dq;
     92	ptrs[disks-1] = q;
     93
     94	/* Now, pick the proper data tables */
     95	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
     96
     97	/* Now do it... */
     98	while (bytes) {
     99		xor_block(dq, q);
    100		for (i = 0; i < 256; i++)
    101			dq[i] = qmul[dq[i]];
    102		xor_block(p, dq);
    103		p += 256;
    104		q += 256;
    105		dq += 256;
    106		bytes -= 256;
    107	}
    108}
    109
    110
    111const struct raid6_recov_calls raid6_recov_s390xc = {
    112	.data2 = raid6_2data_recov_s390xc,
    113	.datap = raid6_datap_recov_s390xc,
    114	.valid = NULL,
    115	.name = "s390xc",
    116	.priority = 1,
    117};