xref: /titanic_52/usr/src/common/hdcrc/hd_crc.h (revision 2a910fbb92dbaed71db5d7843518f08d02ebb922)
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