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