Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "The new features and main improvements in this merge for v4.9 - Support for the UBSAN sanitizer - Set HAVE_EFFICIENT_UNALIGNED_ACCESS, it improves the code in some places - Improvements for the in-kernel fpu code, in particular the overhead for multiple consecutive in kernel fpu users is recuded - Add a SIMD implementation for the RAID6 gen and xor operations - Add RAID6 recovery based on the XC instruction - The PCI DMA flush logic has been improved to increase the speed of the map / unmap operations - The time synchronization code has seen some updates And bug fixes all over the place" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (48 commits) s390/con3270: fix insufficient space padding s390/con3270: fix use of uninitialised data MAINTAINERS: update DASD maintainer s390/cio: fix accidental interrupt enabling during resume s390/dasd: add missing \n to end of dev_err messages s390/config: Enable config options for Docker s390/dasd: make query host access interruptible s390/dasd: fix panic during offline processing s390/dasd: fix hanging offline processing s390/pci_dma: improve lazy flush for unmap s390/pci_dma: split dma_update_trans s390/pci_dma: improve map_sg s390/pci_dma: simplify dma address calculation s390/pci_dma: remove dma address range check iommu/s390: simplify registration of I/O address translation parameters s390: migrate exception table users off module.h and onto extable.h s390: export header for CLP ioctl s390/vmur: fix irq pointer dereference in int handler s390/dasd: add missing KOBJ_CHANGE event for unformatted devices s390: enable UBSAN ...
Tento commit je obsažen v:
@@ -1,6 +1,9 @@
|
||||
config ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
bool
|
||||
|
||||
config ARCH_WANTS_UBSAN_NO_NULL
|
||||
def_bool n
|
||||
|
||||
config UBSAN
|
||||
bool "Undefined behaviour sanity checker"
|
||||
help
|
||||
@@ -34,3 +37,11 @@ config UBSAN_ALIGNMENT
|
||||
This option enables detection of unaligned memory accesses.
|
||||
Enabling this option on architectures that support unaligned
|
||||
accesses may produce a lot of false positives.
|
||||
|
||||
config UBSAN_NULL
|
||||
bool "Enable checking of null pointers"
|
||||
depends on UBSAN
|
||||
default y if !ARCH_WANTS_UBSAN_NO_NULL
|
||||
help
|
||||
This option enables detection of memory accesses via a
|
||||
null pointer.
|
||||
|
1
lib/raid6/.gitignore
vendorováno
1
lib/raid6/.gitignore
vendorováno
@@ -3,3 +3,4 @@ altivec*.c
|
||||
int*.c
|
||||
tables.c
|
||||
neon?.c
|
||||
s390vx?.c
|
||||
|
@@ -7,6 +7,7 @@ raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o
|
||||
raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o
|
||||
raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o
|
||||
raid6_pq-$(CONFIG_TILEGX) += tilegx8.o
|
||||
raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o
|
||||
|
||||
hostprogs-y += mktables
|
||||
|
||||
@@ -116,6 +117,11 @@ $(obj)/tilegx8.c: UNROLL := 8
|
||||
$(obj)/tilegx8.c: $(src)/tilegx.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
targets += s390vx8.c
|
||||
$(obj)/s390vx8.c: UNROLL := 8
|
||||
$(obj)/s390vx8.c: $(src)/s390vx.uc $(src)/unroll.awk FORCE
|
||||
$(call if_changed,unroll)
|
||||
|
||||
quiet_cmd_mktable = TABLE $@
|
||||
cmd_mktable = $(obj)/mktables > $@ || ( rm -f $@ && exit 1 )
|
||||
|
||||
|
@@ -68,6 +68,9 @@ const struct raid6_calls * const raid6_algos[] = {
|
||||
#endif
|
||||
#if defined(CONFIG_TILEGX)
|
||||
&raid6_tilegx8,
|
||||
#endif
|
||||
#if defined(CONFIG_S390)
|
||||
&raid6_s390vx8,
|
||||
#endif
|
||||
&raid6_intx1,
|
||||
&raid6_intx2,
|
||||
@@ -94,6 +97,9 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {
|
||||
#endif
|
||||
#ifdef CONFIG_AS_SSSE3
|
||||
&raid6_recov_ssse3,
|
||||
#endif
|
||||
#ifdef CONFIG_S390
|
||||
&raid6_recov_s390xc,
|
||||
#endif
|
||||
&raid6_recov_intx1,
|
||||
NULL
|
||||
|
116
lib/raid6/recov_s390xc.c
Normální soubor
116
lib/raid6/recov_s390xc.c
Normální soubor
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* RAID-6 data recovery in dual failure mode based on the XC instruction.
|
||||
*
|
||||
* Copyright IBM Corp. 2016
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/raid/pq.h>
|
||||
|
||||
static inline void xor_block(u8 *p1, u8 *p2)
|
||||
{
|
||||
typedef struct { u8 _[256]; } addrtype;
|
||||
|
||||
asm volatile(
|
||||
" xc 0(256,%[p1]),0(%[p2])\n"
|
||||
: "+m" (*(addrtype *) p1) : "m" (*(addrtype *) p2),
|
||||
[p1] "a" (p1), [p2] "a" (p2) : "cc");
|
||||
}
|
||||
|
||||
/* Recover two failed data blocks. */
|
||||
static void raid6_2data_recov_s390xc(int disks, size_t bytes, int faila,
|
||||
int failb, void **ptrs)
|
||||
{
|
||||
u8 *p, *q, *dp, *dq;
|
||||
const u8 *pbmul; /* P multiplier table for B data */
|
||||
const u8 *qmul; /* Q multiplier table (for both) */
|
||||
int i;
|
||||
|
||||
p = (u8 *)ptrs[disks-2];
|
||||
q = (u8 *)ptrs[disks-1];
|
||||
|
||||
/* Compute syndrome with zero for the missing data pages
|
||||
Use the dead data pages as temporary storage for
|
||||
delta p and delta q */
|
||||
dp = (u8 *)ptrs[faila];
|
||||
ptrs[faila] = (void *)raid6_empty_zero_page;
|
||||
ptrs[disks-2] = dp;
|
||||
dq = (u8 *)ptrs[failb];
|
||||
ptrs[failb] = (void *)raid6_empty_zero_page;
|
||||
ptrs[disks-1] = dq;
|
||||
|
||||
raid6_call.gen_syndrome(disks, bytes, ptrs);
|
||||
|
||||
/* Restore pointer table */
|
||||
ptrs[faila] = dp;
|
||||
ptrs[failb] = dq;
|
||||
ptrs[disks-2] = p;
|
||||
ptrs[disks-1] = q;
|
||||
|
||||
/* Now, pick the proper data tables */
|
||||
pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
|
||||
qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
|
||||
|
||||
/* Now do it... */
|
||||
while (bytes) {
|
||||
xor_block(dp, p);
|
||||
xor_block(dq, q);
|
||||
for (i = 0; i < 256; i++)
|
||||
dq[i] = pbmul[dp[i]] ^ qmul[dq[i]];
|
||||
xor_block(dp, dq);
|
||||
p += 256;
|
||||
q += 256;
|
||||
dp += 256;
|
||||
dq += 256;
|
||||
bytes -= 256;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recover failure of one data block plus the P block */
|
||||
static void raid6_datap_recov_s390xc(int disks, size_t bytes, int faila,
|
||||
void **ptrs)
|
||||
{
|
||||
u8 *p, *q, *dq;
|
||||
const u8 *qmul; /* Q multiplier table */
|
||||
int i;
|
||||
|
||||
p = (u8 *)ptrs[disks-2];
|
||||
q = (u8 *)ptrs[disks-1];
|
||||
|
||||
/* Compute syndrome with zero for the missing data page
|
||||
Use the dead data page as temporary storage for delta q */
|
||||
dq = (u8 *)ptrs[faila];
|
||||
ptrs[faila] = (void *)raid6_empty_zero_page;
|
||||
ptrs[disks-1] = dq;
|
||||
|
||||
raid6_call.gen_syndrome(disks, bytes, ptrs);
|
||||
|
||||
/* Restore pointer table */
|
||||
ptrs[faila] = dq;
|
||||
ptrs[disks-1] = q;
|
||||
|
||||
/* Now, pick the proper data tables */
|
||||
qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
|
||||
|
||||
/* Now do it... */
|
||||
while (bytes) {
|
||||
xor_block(dq, q);
|
||||
for (i = 0; i < 256; i++)
|
||||
dq[i] = qmul[dq[i]];
|
||||
xor_block(p, dq);
|
||||
p += 256;
|
||||
q += 256;
|
||||
dq += 256;
|
||||
bytes -= 256;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct raid6_recov_calls raid6_recov_s390xc = {
|
||||
.data2 = raid6_2data_recov_s390xc,
|
||||
.datap = raid6_datap_recov_s390xc,
|
||||
.valid = NULL,
|
||||
.name = "s390xc",
|
||||
.priority = 1,
|
||||
};
|
168
lib/raid6/s390vx.uc
Normální soubor
168
lib/raid6/s390vx.uc
Normální soubor
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* raid6_vx$#.c
|
||||
*
|
||||
* $#-way unrolled RAID6 gen/xor functions for s390
|
||||
* based on the vector facility
|
||||
*
|
||||
* Copyright IBM Corp. 2016
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
*
|
||||
* This file is postprocessed using unroll.awk.
|
||||
*/
|
||||
|
||||
#include <linux/raid/pq.h>
|
||||
#include <asm/fpu/api.h>
|
||||
|
||||
asm(".include \"asm/vx-insn.h\"\n");
|
||||
|
||||
#define NSIZE 16
|
||||
|
||||
static inline void LOAD_CONST(void)
|
||||
{
|
||||
asm volatile("VREPIB %v24,7");
|
||||
asm volatile("VREPIB %v25,0x1d");
|
||||
}
|
||||
|
||||
/*
|
||||
* The SHLBYTE() operation shifts each of the 16 bytes in
|
||||
* vector register y left by 1 bit and stores the result in
|
||||
* vector register x.
|
||||
*/
|
||||
static inline void SHLBYTE(int x, int y)
|
||||
{
|
||||
asm volatile ("VAB %0,%1,%1" : : "i" (x), "i" (y));
|
||||
}
|
||||
|
||||
/*
|
||||
* For each of the 16 bytes in the vector register y the MASK()
|
||||
* operation returns 0xFF if the high bit of the byte is 1,
|
||||
* or 0x00 if the high bit is 0. The result is stored in vector
|
||||
* register x.
|
||||
*/
|
||||
static inline void MASK(int x, int y)
|
||||
{
|
||||
asm volatile ("VESRAVB %0,%1,24" : : "i" (x), "i" (y));
|
||||
}
|
||||
|
||||
static inline void AND(int x, int y, int z)
|
||||
{
|
||||
asm volatile ("VN %0,%1,%2" : : "i" (x), "i" (y), "i" (z));
|
||||
}
|
||||
|
||||
static inline void XOR(int x, int y, int z)
|
||||
{
|
||||
asm volatile ("VX %0,%1,%2" : : "i" (x), "i" (y), "i" (z));
|
||||
}
|
||||
|
||||
static inline void LOAD_DATA(int x, int n, u8 *ptr)
|
||||
{
|
||||
typedef struct { u8 _[16*n]; } addrtype;
|
||||
register addrtype *__ptr asm("1") = (addrtype *) ptr;
|
||||
|
||||
asm volatile ("VLM %2,%3,0,%r1"
|
||||
: : "m" (*__ptr), "a" (__ptr), "i" (x), "i" (x + n - 1));
|
||||
}
|
||||
|
||||
static inline void STORE_DATA(int x, int n, u8 *ptr)
|
||||
{
|
||||
typedef struct { u8 _[16*n]; } addrtype;
|
||||
register addrtype *__ptr asm("1") = (addrtype *) ptr;
|
||||
|
||||
asm volatile ("VSTM %2,%3,0,1"
|
||||
: "=m" (*__ptr) : "a" (__ptr), "i" (x), "i" (x + n - 1));
|
||||
}
|
||||
|
||||
static inline void COPY_VEC(int x, int y)
|
||||
{
|
||||
asm volatile ("VLR %0,%1" : : "i" (x), "i" (y));
|
||||
}
|
||||
|
||||
static void raid6_s390vx$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
|
||||
{
|
||||
struct kernel_fpu vxstate;
|
||||
u8 **dptr, *p, *q;
|
||||
int d, z, z0;
|
||||
|
||||
kernel_fpu_begin(&vxstate, KERNEL_VXR);
|
||||
LOAD_CONST();
|
||||
|
||||
dptr = (u8 **) ptrs;
|
||||
z0 = disks - 3; /* Highest data disk */
|
||||
p = dptr[z0 + 1]; /* XOR parity */
|
||||
q = dptr[z0 + 2]; /* RS syndrome */
|
||||
|
||||
for (d = 0; d < bytes; d += $#*NSIZE) {
|
||||
LOAD_DATA(0,$#,&dptr[z0][d]);
|
||||
COPY_VEC(8+$$,0+$$);
|
||||
for (z = z0 - 1; z >= 0; z--) {
|
||||
MASK(16+$$,8+$$);
|
||||
AND(16+$$,16+$$,25);
|
||||
SHLBYTE(8+$$,8+$$);
|
||||
XOR(8+$$,8+$$,16+$$);
|
||||
LOAD_DATA(16,$#,&dptr[z][d]);
|
||||
XOR(0+$$,0+$$,16+$$);
|
||||
XOR(8+$$,8+$$,16+$$);
|
||||
}
|
||||
STORE_DATA(0,$#,&p[d]);
|
||||
STORE_DATA(8,$#,&q[d]);
|
||||
}
|
||||
kernel_fpu_end(&vxstate, KERNEL_VXR);
|
||||
}
|
||||
|
||||
static void raid6_s390vx$#_xor_syndrome(int disks, int start, int stop,
|
||||
size_t bytes, void **ptrs)
|
||||
{
|
||||
struct kernel_fpu vxstate;
|
||||
u8 **dptr, *p, *q;
|
||||
int d, z, z0;
|
||||
|
||||
dptr = (u8 **) ptrs;
|
||||
z0 = stop; /* P/Q right side optimization */
|
||||
p = dptr[disks - 2]; /* XOR parity */
|
||||
q = dptr[disks - 1]; /* RS syndrome */
|
||||
|
||||
kernel_fpu_begin(&vxstate, KERNEL_VXR);
|
||||
LOAD_CONST();
|
||||
|
||||
for (d = 0; d < bytes; d += $#*NSIZE) {
|
||||
/* P/Q data pages */
|
||||
LOAD_DATA(0,$#,&dptr[z0][d]);
|
||||
COPY_VEC(8+$$,0+$$);
|
||||
for (z = z0 - 1; z >= start; z--) {
|
||||
MASK(16+$$,8+$$);
|
||||
AND(16+$$,16+$$,25);
|
||||
SHLBYTE(8+$$,8+$$);
|
||||
XOR(8+$$,8+$$,16+$$);
|
||||
LOAD_DATA(16,$#,&dptr[z][d]);
|
||||
XOR(0+$$,0+$$,16+$$);
|
||||
XOR(8+$$,8+$$,16+$$);
|
||||
}
|
||||
/* P/Q left side optimization */
|
||||
for (z = start - 1; z >= 0; z--) {
|
||||
MASK(16+$$,8+$$);
|
||||
AND(16+$$,16+$$,25);
|
||||
SHLBYTE(8+$$,8+$$);
|
||||
XOR(8+$$,8+$$,16+$$);
|
||||
}
|
||||
LOAD_DATA(16,$#,&p[d]);
|
||||
XOR(16+$$,16+$$,0+$$);
|
||||
STORE_DATA(16,$#,&p[d]);
|
||||
LOAD_DATA(16,$#,&q[d]);
|
||||
XOR(16+$$,16+$$,8+$$);
|
||||
STORE_DATA(16,$#,&q[d]);
|
||||
}
|
||||
kernel_fpu_end(&vxstate, KERNEL_VXR);
|
||||
}
|
||||
|
||||
static int raid6_s390vx$#_valid(void)
|
||||
{
|
||||
return MACHINE_HAS_VX;
|
||||
}
|
||||
|
||||
const struct raid6_calls raid6_s390vx$# = {
|
||||
raid6_s390vx$#_gen_syndrome,
|
||||
raid6_s390vx$#_xor_syndrome,
|
||||
raid6_s390vx$#_valid,
|
||||
"vx128x$#",
|
||||
1
|
||||
};
|
Odkázat v novém úkolu
Zablokovat Uživatele