Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / crc32c_ppc.c
1 /* Copyright (C) 2017 International Business Machines Corp.
2  * All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version
7  * 2 of the License, or (at your option) any later version.
8  */
9 #define CRC_TABLE
10 #define FAST_ZERO_TABLE
11
12 #include "acconfig.h"
13 #include "include/int_types.h"
14 #include "crc32c_ppc_constants.h"
15 #include "reverse.h"
16
17 #include <stdlib.h>
18 #include <strings.h>
19
20 #define VMX_ALIGN       16
21 #define VMX_ALIGN_MASK  (VMX_ALIGN-1)
22
23 #ifdef REFLECT
24 static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
25                                 unsigned long len)
26 {
27   while (len--)
28     crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
29   return crc;
30 }
31 #else
32 static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
33                                 unsigned long len)
34 {
35   while (len--)
36     crc = crc_table[((crc >> 24) ^ *p++) & 0xff] ^ (crc << 8);
37   return crc;
38 }
39 #endif
40
41 #ifdef HAVE_POWER8
42 static inline unsigned long polynomial_multiply(unsigned int a, unsigned int b) {
43         vector unsigned int va = {a, 0, 0, 0};
44         vector unsigned int vb = {b, 0, 0, 0};
45         vector unsigned long vt;
46
47         __asm__("vpmsumw %0,%1,%2" : "=v"(vt) : "v"(va), "v"(vb));
48
49         return vt[0];
50 }
51
52 unsigned int barrett_reduction(unsigned long val);
53
54 static inline unsigned int gf_multiply(unsigned int a, unsigned int b) {
55         return barrett_reduction(polynomial_multiply(a, b));
56 }
57
58 unsigned int append_zeros(unsigned int crc, unsigned long length) {
59         unsigned long i = 0;
60
61         while (length) {
62                 if (length & 1) {
63                         crc = gf_multiply(crc, crc_zero[i]);
64                 }
65                 i++;
66                 length /= 2;
67         }
68
69         return crc;
70 }
71
72
73 unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p,
74                             unsigned long len);
75
76 static uint32_t crc32_vpmsum(uint32_t crc, unsigned char const *data,
77                              unsigned len)
78 {
79   unsigned int prealign;
80   unsigned int tail;
81
82 #ifdef CRC_XOR
83   crc ^= 0xffffffff;
84 #endif
85
86   if (len < VMX_ALIGN + VMX_ALIGN_MASK) {
87     crc = crc32_align(crc, data, (unsigned long)len);
88     goto out;
89   }
90
91   if ((unsigned long)data & VMX_ALIGN_MASK) {
92     prealign = VMX_ALIGN - ((unsigned long)data & VMX_ALIGN_MASK);
93     crc = crc32_align(crc, data, prealign);
94     len -= prealign;
95     data += prealign;
96   }
97
98   crc = __crc32_vpmsum(crc, data, (unsigned long)len & ~VMX_ALIGN_MASK);
99
100   tail = len & VMX_ALIGN_MASK;
101   if (tail) {
102     data += len & ~VMX_ALIGN_MASK;
103     crc = crc32_align(crc, data, tail);
104   }
105
106 out:
107 #ifdef CRC_XOR
108   crc ^= 0xffffffff;
109 #endif
110
111   return crc;
112 }
113
114 /* This wrapper function works around the fact that crc32_vpmsum 
115  * does not gracefully handle the case where the data pointer is NULL.
116  */
117 uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
118 {
119   if (!data) {
120     /* Handle the NULL buffer case. */
121 #ifdef REFLECT
122     crc = reverse_bits(crc);
123 #endif
124
125     crc = append_zeros(crc, len);
126
127 #ifdef REFLECT
128     crc = reverse_bits(crc);
129 #endif
130   } else {
131     /* Handle the valid buffer case. */
132     crc = crc32_vpmsum(crc, data, (unsigned long)len);
133   }
134   return crc;
135 }
136
137 #else /* HAVE_POWER8 */
138
139 /* This symbol has to exist on non-ppc architectures (and on legacy
140  * ppc systems using power7 or below) in order to compile properly
141  * there, even though it won't be called.
142  */
143 uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
144 {
145   return 0;
146 }
147
148 #endif /* HAVE_POWER8 */