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 /* 28*7417cfdeSKuriakose Kuruvilla * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 29d4b0f847SJack Meng */ 30d4b0f847SJack Meng 31d4b0f847SJack Meng #ifndef _CRC_HD_H 32d4b0f847SJack Meng #define _CRC_HD_H 33d4b0f847SJack Meng 34d4b0f847SJack Meng #ifdef __cplusplus 35d4b0f847SJack Meng extern "C" { 36d4b0f847SJack Meng #endif 37d4b0f847SJack Meng 38d4b0f847SJack Meng #include <sys/types.h> 39d4b0f847SJack Meng 40d4b0f847SJack Meng #ifdef __cplusplus 41d4b0f847SJack Meng #ifndef INLINE 42d4b0f847SJack Meng #define INLINE inline 43d4b0f847SJack Meng #endif 44d4b0f847SJack Meng #else 45d4b0f847SJack Meng #ifndef INLINE 46d4b0f847SJack Meng #define INLINE 47d4b0f847SJack Meng #endif 48d4b0f847SJack Meng #endif 49d4b0f847SJack Meng 50d4b0f847SJack Meng #if defined(__i386) || defined(__amd_64) || defined(__x86_64) 51d4b0f847SJack Meng 52d4b0f847SJack Meng #ifdef _KERNEL 53*7417cfdeSKuriakose Kuruvilla #include <sys/x86_archext.h> /* x86_featureset, X86FSET_SSE4_2 */ 542a910fbbSJack Meng 55d4b0f847SJack Meng #else 562a910fbbSJack Meng 572a910fbbSJack Meng #include <sys/auxv.h> /* getisax() */ 58*7417cfdeSKuriakose Kuruvilla #include <sys/auxv_386.h> /* AV_386_SSE4_2 bit */ 592a910fbbSJack Meng 602a910fbbSJack Meng #endif 61d4b0f847SJack Meng 62d4b0f847SJack Meng static INLINE uint32_t 63d4b0f847SJack Meng #ifdef _KERNEL 64d4b0f847SJack Meng /*LINTED:E_FUNC_ARG_UNUSED*/ 65d4b0f847SJack Meng mm_crc32_u8(uint32_t crc, uint8_t *data) 66d4b0f847SJack Meng #else 67d4b0f847SJack Meng mm_crc32_u8(uint32_t crc, uint8_t *data) 68d4b0f847SJack Meng #endif /* _KERNEL */ 69d4b0f847SJack Meng { 70d4b0f847SJack Meng __asm__ __volatile__( 71d4b0f847SJack Meng /* "crc32 r32, r/m8" */ 72d4b0f847SJack Meng ".byte 0xF2, 0x0F, 0x38, 0xF0, 0xF1" 73d4b0f847SJack Meng : "=S" (crc) 74d4b0f847SJack Meng : "0" (crc), "c" (*data)); 75d4b0f847SJack Meng 76d4b0f847SJack Meng return (crc); 77d4b0f847SJack Meng } 78d4b0f847SJack Meng 79d4b0f847SJack Meng #if defined(__amd64) || defined(__x86_64) 80d4b0f847SJack Meng 81d4b0f847SJack Meng static INLINE uint32_t 82d4b0f847SJack Meng #ifdef _KERNEL 83d4b0f847SJack Meng /*LINTED:E_FUNC_ARG_UNUSED*/ 84d4b0f847SJack Meng mm_crc32_u64(uint32_t crc, uint64_t *data) 85d4b0f847SJack Meng #else 86d4b0f847SJack Meng mm_crc32_u64(uint32_t crc, uint64_t *data) 87d4b0f847SJack Meng #endif /* _KERNEL */ 88d4b0f847SJack Meng { 89d4b0f847SJack Meng __asm__ __volatile__( 90d4b0f847SJack Meng /* "crc32 r32, r/m64" */ 91d4b0f847SJack Meng ".byte 0xF2, 0x48, 0x0F, 0x38, 0xF1, 0xF1" 92d4b0f847SJack Meng : "=S" (crc) 93d4b0f847SJack Meng : "0" (crc), "c" (*data)); 94d4b0f847SJack Meng 95d4b0f847SJack Meng return (crc); 96d4b0f847SJack Meng } 97d4b0f847SJack Meng 98d4b0f847SJack Meng #define INTEL_CRC_ALIGN_MASK 0x7 99d4b0f847SJack Meng #define INTEL_CRC_SIZE 8 100d4b0f847SJack Meng #define INTEL_CRC_DATA_TYPE uint64_t 101d4b0f847SJack Meng #define INTEL_CRC_FUNC mm_crc32_u64 102d4b0f847SJack Meng 103d4b0f847SJack Meng #else 104d4b0f847SJack Meng 105d4b0f847SJack Meng static INLINE uint32_t 106d4b0f847SJack Meng #ifdef _KERNEL 107d4b0f847SJack Meng /*LINTED:E_FUNC_ARG_UNUSED*/ 108d4b0f847SJack Meng mm_crc32_u32(uint32_t crc, uint32_t *data) 109d4b0f847SJack Meng #else 110d4b0f847SJack Meng mm_crc32_u32(uint32_t crc, uint32_t *data) 111d4b0f847SJack Meng #endif /* _KERNEL */ 112d4b0f847SJack Meng { 113d4b0f847SJack Meng __asm__ __volatile__( 114d4b0f847SJack Meng /* "crc32 r32, r/m32" */ 115d4b0f847SJack Meng ".byte 0xF2, 0x0F, 0x38, 0xF1, 0xF1" 116d4b0f847SJack Meng : "=S" (crc) 117d4b0f847SJack Meng : "0" (crc), "c" (*data)); 118d4b0f847SJack Meng 119d4b0f847SJack Meng return (crc); 120d4b0f847SJack Meng } 121d4b0f847SJack Meng 122d4b0f847SJack Meng #define INTEL_CRC_ALIGN_MASK 0x3 123d4b0f847SJack Meng #define INTEL_CRC_SIZE 4 124d4b0f847SJack Meng #define INTEL_CRC_DATA_TYPE uint32_t 125d4b0f847SJack Meng #define INTEL_CRC_FUNC mm_crc32_u32 126d4b0f847SJack Meng 127d4b0f847SJack Meng #endif 128d4b0f847SJack Meng 129d4b0f847SJack Meng static INLINE uint32_t 130d4b0f847SJack Meng intel_crc32c(uint8_t *address, unsigned long length, uint32_t crc) 131d4b0f847SJack Meng { 132d4b0f847SJack Meng uint32_t i = (uintptr_t)address & INTEL_CRC_ALIGN_MASK; 133d4b0f847SJack Meng uint8_t *data = address; 134d4b0f847SJack Meng 135d4b0f847SJack Meng /* Process unaligned header data */ 136d4b0f847SJack Meng while ((length > 0) && (i > 0)) { 137d4b0f847SJack Meng crc = mm_crc32_u8(crc, data); 138d4b0f847SJack Meng ++ data; 139d4b0f847SJack Meng -- length; 140d4b0f847SJack Meng i ++; 141d4b0f847SJack Meng i &= INTEL_CRC_ALIGN_MASK; 142d4b0f847SJack Meng } 143d4b0f847SJack Meng 144d4b0f847SJack Meng /* aligned data part */ 145d4b0f847SJack Meng while (length >= INTEL_CRC_SIZE) { 146d4b0f847SJack Meng /*LINTED:E_BAD_PTR_CAST_ALIGN*/ 147d4b0f847SJack Meng crc = INTEL_CRC_FUNC(crc, (INTEL_CRC_DATA_TYPE *)data); 148d4b0f847SJack Meng data += INTEL_CRC_SIZE; 149d4b0f847SJack Meng length -= INTEL_CRC_SIZE; 150d4b0f847SJack Meng } 151d4b0f847SJack Meng 152d4b0f847SJack Meng /* unaligned tail data */ 153d4b0f847SJack Meng while (length > 0) { 154d4b0f847SJack Meng crc = mm_crc32_u8(crc, data); 155d4b0f847SJack Meng ++ data; 156d4b0f847SJack Meng -- length; 157d4b0f847SJack Meng } 158d4b0f847SJack Meng 159d4b0f847SJack Meng return (crc ^ 0xFFFFFFFF); 160d4b0f847SJack Meng } 161d4b0f847SJack Meng 162d4b0f847SJack Meng #define HW_CRC32(buffer, length, crc) (intel_crc32c((buffer), (length), (crc))) 163d4b0f847SJack Meng #define HW_CRC32_CONT(buffer, length, crc) \ 164d4b0f847SJack Meng (intel_crc32c((buffer), (length), (crc) ^ 0xFFFFFFFF)) 165d4b0f847SJack Meng #else 166d4b0f847SJack Meng #define HW_CRC32(buffer, length, crc) 0 167d4b0f847SJack Meng #define HW_CRC32_CONT(buffer, length, crc) 0 168d4b0f847SJack Meng #endif 169d4b0f847SJack Meng 170d4b0f847SJack Meng static INLINE boolean_t 171d4b0f847SJack Meng #if defined(_KERNEL) && !defined(__i386) && !defined(__amd_64) &&\ 172d4b0f847SJack Meng !defined(__x86_64) 173d4b0f847SJack Meng /*LINTED:E_FUNC_ARG_UNUSED*/ 174d4b0f847SJack Meng hd_crc32_avail(uint32_t *crc32_table) 175d4b0f847SJack Meng #else 176d4b0f847SJack Meng hd_crc32_avail(uint32_t *crc32_table) 177d4b0f847SJack Meng #endif 178d4b0f847SJack Meng { 179d4b0f847SJack Meng #if defined(__i386) || defined(__amd_64) || defined(__x86_64) 180d4b0f847SJack Meng int i; 181d4b0f847SJack Meng /* poly = 0x1EDC6F41 */ 182d4b0f847SJack Meng static const uint32_t _intel_crc32_hd_table[256] = { 183d4b0f847SJack Meng 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 184d4b0f847SJack Meng 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 185d4b0f847SJack Meng 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 186d4b0f847SJack Meng 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 187d4b0f847SJack Meng 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 188d4b0f847SJack Meng 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 189d4b0f847SJack Meng 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 190d4b0f847SJack Meng 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 191d4b0f847SJack Meng 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 192d4b0f847SJack Meng 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 193d4b0f847SJack Meng 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 194d4b0f847SJack Meng 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 195d4b0f847SJack Meng 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 196d4b0f847SJack Meng 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 197d4b0f847SJack Meng 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 198d4b0f847SJack Meng 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 199d4b0f847SJack Meng 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 200d4b0f847SJack Meng 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 201d4b0f847SJack Meng 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 202d4b0f847SJack Meng 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 203d4b0f847SJack Meng 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 204d4b0f847SJack Meng 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 205d4b0f847SJack Meng 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 206d4b0f847SJack Meng 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 207d4b0f847SJack Meng 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 208d4b0f847SJack Meng 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 209d4b0f847SJack Meng 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 210d4b0f847SJack Meng 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 211d4b0f847SJack Meng 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 212d4b0f847SJack Meng 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 213d4b0f847SJack Meng 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 214d4b0f847SJack Meng 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 215d4b0f847SJack Meng 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 216d4b0f847SJack Meng 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 217d4b0f847SJack Meng 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 218d4b0f847SJack Meng 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 219d4b0f847SJack Meng 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 220d4b0f847SJack Meng 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 221d4b0f847SJack Meng 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 222d4b0f847SJack Meng 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 223d4b0f847SJack Meng 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 224d4b0f847SJack Meng 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 225d4b0f847SJack Meng 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 226d4b0f847SJack Meng 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 227d4b0f847SJack Meng 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 228d4b0f847SJack Meng 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 229d4b0f847SJack Meng 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 230d4b0f847SJack Meng 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 231d4b0f847SJack Meng 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 232d4b0f847SJack Meng 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 233d4b0f847SJack Meng 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 234d4b0f847SJack Meng 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 235d4b0f847SJack Meng 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 236d4b0f847SJack Meng 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 237d4b0f847SJack Meng 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 238d4b0f847SJack Meng 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 239d4b0f847SJack Meng 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 240d4b0f847SJack Meng 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 241d4b0f847SJack Meng 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 242d4b0f847SJack Meng 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 243d4b0f847SJack Meng 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 244d4b0f847SJack Meng 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 245d4b0f847SJack Meng 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 246d4b0f847SJack Meng 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 247d4b0f847SJack Meng }; 248d4b0f847SJack Meng 2492a910fbbSJack Meng #ifdef _KERNEL 250*7417cfdeSKuriakose Kuruvilla if (!is_x86_feature(x86_featureset, X86FSET_SSE4_2)) { 2512a910fbbSJack Meng return (B_FALSE); 2522a910fbbSJack Meng } else { 2532a910fbbSJack Meng #else 2542a910fbbSJack Meng { 2552a910fbbSJack Meng uint_t ui = 0; 2562a910fbbSJack Meng 2572a910fbbSJack Meng (void) getisax(&ui, 1); 2582a910fbbSJack Meng 2592a910fbbSJack Meng if (!(ui & AV_386_SSE4_2)) { 2602a910fbbSJack Meng return (B_FALSE); 2612a910fbbSJack Meng } 2622a910fbbSJack Meng #endif /* _KERNEL */ 263d4b0f847SJack Meng for (i = 0; i < 256; i++) { 264d4b0f847SJack Meng if (crc32_table[i] != _intel_crc32_hd_table[i]) 265d4b0f847SJack Meng return (B_FALSE); 266d4b0f847SJack Meng } 267d4b0f847SJack Meng return (B_TRUE); 268d4b0f847SJack Meng } 2692a910fbbSJack Meng #else 270d4b0f847SJack Meng return (B_FALSE); 2712a910fbbSJack Meng #endif 272d4b0f847SJack Meng } 273d4b0f847SJack Meng 274d4b0f847SJack Meng #ifdef __cplusplus 275d4b0f847SJack Meng } 276d4b0f847SJack Meng #endif 277d4b0f847SJack Meng 278d4b0f847SJack Meng #endif /* _CRC_HD_H */ 279