]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - module/zcommon/zfs_fletcher_superscalar.c
Add zpool status -s (slow I/Os) and -p (parseable)
[FreeBSD/FreeBSD.git] / module / zcommon / zfs_fletcher_superscalar.c
1 /*
2  * Implement fast Fletcher4 using superscalar pipelines.
3  *
4  * Use regular C code to compute
5  * Fletcher4 in two incremental 64-bit parallel accumulator streams,
6  * and then combine the streams to form the final four checksum words.
7  * This implementation is a derivative of the AVX SIMD implementation by
8  * James Guilford and Jinshan Xiong from Intel (see zfs_fletcher_intel.c).
9  *
10  * Copyright (C) 2016 Romain Dolbeau.
11  *
12  * Authors:
13  *      Romain Dolbeau <romain.dolbeau@atos.net>
14  *
15  * This software is available to you under a choice of one of two
16  * licenses.  You may choose to be licensed under the terms of the GNU
17  * General Public License (GPL) Version 2, available from the file
18  * COPYING in the main directory of this source tree, or the
19  * OpenIB.org BSD license below:
20  *
21  *     Redistribution and use in source and binary forms, with or
22  *     without modification, are permitted provided that the following
23  *     conditions are met:
24  *
25  *      - Redistributions of source code must retain the above
26  *        copyright notice, this list of conditions and the following
27  *        disclaimer.
28  *
29  *      - Redistributions in binary form must reproduce the above
30  *        copyright notice, this list of conditions and the following
31  *        disclaimer in the documentation and/or other materials
32  *        provided with the distribution.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
38  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
39  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41  * SOFTWARE.
42  */
43
44 #include <sys/byteorder.h>
45 #include <sys/spa_checksum.h>
46 #include <sys/strings.h>
47 #include <zfs_fletcher.h>
48
49 static void
50 fletcher_4_superscalar_init(fletcher_4_ctx_t *ctx)
51 {
52         bzero(ctx->superscalar, 4 * sizeof (zfs_fletcher_superscalar_t));
53 }
54
55 static void
56 fletcher_4_superscalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
57 {
58         uint64_t A, B, C, D;
59         A = ctx->superscalar[0].v[0] + ctx->superscalar[0].v[1];
60         B = 2 * ctx->superscalar[1].v[0] + 2 * ctx->superscalar[1].v[1] -
61             ctx->superscalar[0].v[1];
62         C = 4 * ctx->superscalar[2].v[0] - ctx->superscalar[1].v[0] +
63             4 * ctx->superscalar[2].v[1] - 3 * ctx->superscalar[1].v[1];
64         D = 8 * ctx->superscalar[3].v[0] - 4 * ctx->superscalar[2].v[0] +
65             8 * ctx->superscalar[3].v[1] - 8 * ctx->superscalar[2].v[1] +
66             ctx->superscalar[1].v[1];
67         ZIO_SET_CHECKSUM(zcp, A, B, C, D);
68 }
69
70 static void
71 fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
72     const void *buf, uint64_t size)
73 {
74         const uint32_t *ip = buf;
75         const uint32_t *ipend = ip + (size / sizeof (uint32_t));
76         uint64_t a, b, c, d;
77         uint64_t a2, b2, c2, d2;
78
79         a = ctx->superscalar[0].v[0];
80         b = ctx->superscalar[1].v[0];
81         c = ctx->superscalar[2].v[0];
82         d = ctx->superscalar[3].v[0];
83         a2 = ctx->superscalar[0].v[1];
84         b2 = ctx->superscalar[1].v[1];
85         c2 = ctx->superscalar[2].v[1];
86         d2 = ctx->superscalar[3].v[1];
87
88         for (; ip < ipend; ip += 2) {
89                 a += ip[0];
90                 a2 += ip[1];
91                 b += a;
92                 b2 += a2;
93                 c += b;
94                 c2 += b2;
95                 d += c;
96                 d2 += c2;
97         }
98
99         ctx->superscalar[0].v[0] = a;
100         ctx->superscalar[1].v[0] = b;
101         ctx->superscalar[2].v[0] = c;
102         ctx->superscalar[3].v[0] = d;
103         ctx->superscalar[0].v[1] = a2;
104         ctx->superscalar[1].v[1] = b2;
105         ctx->superscalar[2].v[1] = c2;
106         ctx->superscalar[3].v[1] = d2;
107 }
108
109 static void
110 fletcher_4_superscalar_byteswap(fletcher_4_ctx_t *ctx,
111     const void *buf, uint64_t size)
112 {
113         const uint32_t *ip = buf;
114         const uint32_t *ipend = ip + (size / sizeof (uint32_t));
115         uint64_t a, b, c, d;
116         uint64_t a2, b2, c2, d2;
117
118         a = ctx->superscalar[0].v[0];
119         b = ctx->superscalar[1].v[0];
120         c = ctx->superscalar[2].v[0];
121         d = ctx->superscalar[3].v[0];
122         a2 = ctx->superscalar[0].v[1];
123         b2 = ctx->superscalar[1].v[1];
124         c2 = ctx->superscalar[2].v[1];
125         d2 = ctx->superscalar[3].v[1];
126
127         for (; ip < ipend; ip += 2) {
128                 a += BSWAP_32(ip[0]);
129                 a2 += BSWAP_32(ip[1]);
130                 b += a;
131                 b2 += a2;
132                 c += b;
133                 c2 += b2;
134                 d += c;
135                 d2 += c2;
136         }
137
138         ctx->superscalar[0].v[0] = a;
139         ctx->superscalar[1].v[0] = b;
140         ctx->superscalar[2].v[0] = c;
141         ctx->superscalar[3].v[0] = d;
142         ctx->superscalar[0].v[1] = a2;
143         ctx->superscalar[1].v[1] = b2;
144         ctx->superscalar[2].v[1] = c2;
145         ctx->superscalar[3].v[1] = d2;
146 }
147
148 static boolean_t fletcher_4_superscalar_valid(void)
149 {
150         return (B_TRUE);
151 }
152
153 const fletcher_4_ops_t fletcher_4_superscalar_ops = {
154         .init_native = fletcher_4_superscalar_init,
155         .compute_native = fletcher_4_superscalar_native,
156         .fini_native = fletcher_4_superscalar_fini,
157         .init_byteswap = fletcher_4_superscalar_init,
158         .compute_byteswap = fletcher_4_superscalar_byteswap,
159         .fini_byteswap = fletcher_4_superscalar_fini,
160         .valid = fletcher_4_superscalar_valid,
161         .name = "superscalar"
162 };