1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, Intel Corporation. 24 * All rights reserved. 25 */ 26 27 /* 28 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 #ifndef _CRC_HD_H 33 #define _CRC_HD_H 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 #include <sys/types.h> 40 41 #ifdef __cplusplus 42 #ifndef INLINE 43 #define INLINE inline 44 #endif 45 #else 46 #ifndef INLINE 47 #define INLINE 48 #endif 49 #endif 50 51 #if defined(__i386) || defined(__amd_64) || defined(__x86_64) 52 53 #define INTEL_CPU_FEATURE_SSE42 0x0100000 54 55 static INLINE unsigned int 56 #ifdef _KERNEL 57 /*LINTED:E_FUNC_ARG_UNUSED*/ 58 cpuid_ecx(unsigned int op) 59 #else 60 cpuid_ecx(unsigned int op) 61 #endif /* _KERNEL */ 62 { 63 /*LINTED:E_FUNC_VAR_UNUSED*/ 64 unsigned int eax, ecx; 65 __asm__ __volatile__("cpuid" 66 : "=a" (eax), "=c" (ecx) 67 : "0" (op) 68 : "bx", "dx"); 69 /*LINTED:E_VAR_USED_BEFORE_SET*/ 70 return (ecx); 71 } 72 73 static INLINE uint32_t 74 #ifdef _KERNEL 75 /*LINTED:E_FUNC_ARG_UNUSED*/ 76 mm_crc32_u8(uint32_t crc, uint8_t *data) 77 #else 78 mm_crc32_u8(uint32_t crc, uint8_t *data) 79 #endif /* _KERNEL */ 80 { 81 __asm__ __volatile__( 82 /* "crc32 r32, r/m8" */ 83 ".byte 0xF2, 0x0F, 0x38, 0xF0, 0xF1" 84 : "=S" (crc) 85 : "0" (crc), "c" (*data)); 86 87 return (crc); 88 } 89 90 #if defined(__amd64) || defined(__x86_64) 91 92 static INLINE uint32_t 93 #ifdef _KERNEL 94 /*LINTED:E_FUNC_ARG_UNUSED*/ 95 mm_crc32_u64(uint32_t crc, uint64_t *data) 96 #else 97 mm_crc32_u64(uint32_t crc, uint64_t *data) 98 #endif /* _KERNEL */ 99 { 100 __asm__ __volatile__( 101 /* "crc32 r32, r/m64" */ 102 ".byte 0xF2, 0x48, 0x0F, 0x38, 0xF1, 0xF1" 103 : "=S" (crc) 104 : "0" (crc), "c" (*data)); 105 106 return (crc); 107 } 108 109 #define INTEL_CRC_ALIGN_MASK 0x7 110 #define INTEL_CRC_SIZE 8 111 #define INTEL_CRC_DATA_TYPE uint64_t 112 #define INTEL_CRC_FUNC mm_crc32_u64 113 114 #else 115 116 static INLINE uint32_t 117 #ifdef _KERNEL 118 /*LINTED:E_FUNC_ARG_UNUSED*/ 119 mm_crc32_u32(uint32_t crc, uint32_t *data) 120 #else 121 mm_crc32_u32(uint32_t crc, uint32_t *data) 122 #endif /* _KERNEL */ 123 { 124 __asm__ __volatile__( 125 /* "crc32 r32, r/m32" */ 126 ".byte 0xF2, 0x0F, 0x38, 0xF1, 0xF1" 127 : "=S" (crc) 128 : "0" (crc), "c" (*data)); 129 130 return (crc); 131 } 132 133 #define INTEL_CRC_ALIGN_MASK 0x3 134 #define INTEL_CRC_SIZE 4 135 #define INTEL_CRC_DATA_TYPE uint32_t 136 #define INTEL_CRC_FUNC mm_crc32_u32 137 138 #endif 139 140 static INLINE uint32_t 141 intel_crc32c(uint8_t *address, unsigned long length, uint32_t crc) 142 { 143 uint32_t i = (uintptr_t)address & INTEL_CRC_ALIGN_MASK; 144 uint8_t *data = address; 145 146 /* Process unaligned header data */ 147 while ((length > 0) && (i > 0)) { 148 crc = mm_crc32_u8(crc, data); 149 ++ data; 150 -- length; 151 i ++; 152 i &= INTEL_CRC_ALIGN_MASK; 153 } 154 155 /* aligned data part */ 156 while (length >= INTEL_CRC_SIZE) { 157 /*LINTED:E_BAD_PTR_CAST_ALIGN*/ 158 crc = INTEL_CRC_FUNC(crc, (INTEL_CRC_DATA_TYPE *)data); 159 data += INTEL_CRC_SIZE; 160 length -= INTEL_CRC_SIZE; 161 } 162 163 /* unaligned tail data */ 164 while (length > 0) { 165 crc = mm_crc32_u8(crc, data); 166 ++ data; 167 -- length; 168 } 169 170 return (crc ^ 0xFFFFFFFF); 171 } 172 173 #define HW_CRC32(buffer, length, crc) (intel_crc32c((buffer), (length), (crc))) 174 #define HW_CRC32_CONT(buffer, length, crc) \ 175 (intel_crc32c((buffer), (length), (crc) ^ 0xFFFFFFFF)) 176 #else 177 #define HW_CRC32(buffer, length, crc) 0 178 #define HW_CRC32_CONT(buffer, length, crc) 0 179 #endif 180 181 static INLINE boolean_t 182 #if defined(_KERNEL) && !defined(__i386) && !defined(__amd_64) &&\ 183 !defined(__x86_64) 184 /*LINTED:E_FUNC_ARG_UNUSED*/ 185 hd_crc32_avail(uint32_t *crc32_table) 186 #else 187 hd_crc32_avail(uint32_t *crc32_table) 188 #endif 189 { 190 #if defined(__i386) || defined(__amd_64) || defined(__x86_64) 191 int i; 192 /* poly = 0x1EDC6F41 */ 193 static const uint32_t _intel_crc32_hd_table[256] = { 194 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 195 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 196 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 197 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 198 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 199 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 200 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 201 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 202 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 203 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 204 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 205 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 206 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 207 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 208 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 209 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 210 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 211 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 212 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 213 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 214 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 215 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 216 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 217 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 218 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 219 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 220 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 221 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 222 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 223 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 224 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 225 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 226 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 227 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 228 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 229 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 230 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 231 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 232 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 233 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 234 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 235 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 236 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 237 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 238 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 239 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 240 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 241 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 242 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 243 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 244 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 245 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 246 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 247 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 248 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 249 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 250 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 251 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 252 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 253 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 254 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 255 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 256 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 257 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 258 }; 259 260 if ((cpuid_ecx(1) & INTEL_CPU_FEATURE_SSE42) != 0) { 261 for (i = 0; i < 256; i++) { 262 if (crc32_table[i] != _intel_crc32_hd_table[i]) 263 return (B_FALSE); 264 } 265 return (B_TRUE); 266 } 267 #endif 268 return (B_FALSE); 269 } 270 271 #ifdef __cplusplus 272 } 273 #endif 274 275 #endif /* _CRC_HD_H */ 276