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.c (3405B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* -*- linux-c -*- ------------------------------------------------------- *
      3 *
      4 *   Copyright 2002 H. Peter Anvin - All Rights Reserved
      5 *
      6 * ----------------------------------------------------------------------- */
      7
      8/*
      9 * raid6/recov.c
     10 *
     11 * RAID-6 data recovery in dual failure mode.  In single failure mode,
     12 * use the RAID-5 algorithm (or, in the case of Q failure, just reconstruct
     13 * the syndrome.)
     14 */
     15
     16#include <linux/export.h>
     17#include <linux/raid/pq.h>
     18
     19/* Recover two failed data blocks. */
     20static void raid6_2data_recov_intx1(int disks, size_t bytes, int faila,
     21		int failb, void **ptrs)
     22{
     23	u8 *p, *q, *dp, *dq;
     24	u8 px, qx, db;
     25	const u8 *pbmul;	/* P multiplier table for B data */
     26	const u8 *qmul;		/* Q multiplier table (for both) */
     27
     28	p = (u8 *)ptrs[disks-2];
     29	q = (u8 *)ptrs[disks-1];
     30
     31	/* Compute syndrome with zero for the missing data pages
     32	   Use the dead data pages as temporary storage for
     33	   delta p and delta q */
     34	dp = (u8 *)ptrs[faila];
     35	ptrs[faila] = (void *)raid6_empty_zero_page;
     36	ptrs[disks-2] = dp;
     37	dq = (u8 *)ptrs[failb];
     38	ptrs[failb] = (void *)raid6_empty_zero_page;
     39	ptrs[disks-1] = dq;
     40
     41	raid6_call.gen_syndrome(disks, bytes, ptrs);
     42
     43	/* Restore pointer table */
     44	ptrs[faila]   = dp;
     45	ptrs[failb]   = dq;
     46	ptrs[disks-2] = p;
     47	ptrs[disks-1] = q;
     48
     49	/* Now, pick the proper data tables */
     50	pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
     51	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
     52
     53	/* Now do it... */
     54	while ( bytes-- ) {
     55		px    = *p ^ *dp;
     56		qx    = qmul[*q ^ *dq];
     57		*dq++ = db = pbmul[px] ^ qx; /* Reconstructed B */
     58		*dp++ = db ^ px; /* Reconstructed A */
     59		p++; q++;
     60	}
     61}
     62
     63/* Recover failure of one data block plus the P block */
     64static void raid6_datap_recov_intx1(int disks, size_t bytes, int faila,
     65		void **ptrs)
     66{
     67	u8 *p, *q, *dq;
     68	const u8 *qmul;		/* Q multiplier table */
     69
     70	p = (u8 *)ptrs[disks-2];
     71	q = (u8 *)ptrs[disks-1];
     72
     73	/* Compute syndrome with zero for the missing data page
     74	   Use the dead data page as temporary storage for delta q */
     75	dq = (u8 *)ptrs[faila];
     76	ptrs[faila] = (void *)raid6_empty_zero_page;
     77	ptrs[disks-1] = dq;
     78
     79	raid6_call.gen_syndrome(disks, bytes, ptrs);
     80
     81	/* Restore pointer table */
     82	ptrs[faila]   = dq;
     83	ptrs[disks-1] = q;
     84
     85	/* Now, pick the proper data tables */
     86	qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
     87
     88	/* Now do it... */
     89	while ( bytes-- ) {
     90		*p++ ^= *dq = qmul[*q ^ *dq];
     91		q++; dq++;
     92	}
     93}
     94
     95
     96const struct raid6_recov_calls raid6_recov_intx1 = {
     97	.data2 = raid6_2data_recov_intx1,
     98	.datap = raid6_datap_recov_intx1,
     99	.valid = NULL,
    100	.name = "intx1",
    101	.priority = 0,
    102};
    103
    104#ifndef __KERNEL__
    105/* Testing only */
    106
    107/* Recover two failed blocks. */
    108void raid6_dual_recov(int disks, size_t bytes, int faila, int failb, void **ptrs)
    109{
    110	if ( faila > failb ) {
    111		int tmp = faila;
    112		faila = failb;
    113		failb = tmp;
    114	}
    115
    116	if ( failb == disks-1 ) {
    117		if ( faila == disks-2 ) {
    118			/* P+Q failure.  Just rebuild the syndrome. */
    119			raid6_call.gen_syndrome(disks, bytes, ptrs);
    120		} else {
    121			/* data+Q failure.  Reconstruct data from P,
    122			   then rebuild syndrome. */
    123			/* NOT IMPLEMENTED - equivalent to RAID-5 */
    124		}
    125	} else {
    126		if ( failb == disks-2 ) {
    127			/* data+P failure. */
    128			raid6_datap_recov(disks, bytes, faila, ptrs);
    129		} else {
    130			/* data+data failure. */
    131			raid6_2data_recov(disks, bytes, faila, failb, ptrs);
    132		}
    133	}
    134}
    135
    136#endif