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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <fp.h>
32 #include <fps_ereport.h>
33
34 #pragma align 64(datain1, datain2, dataout)
35
36 int cbbcopy(struct fps_test_ereport *report);
37 static void asi_bcopy_f0(uint32_t *out, uint32_t *in);
38 static void asi_bcopy_f16(uint32_t *out, uint32_t *in);
39 static void ax_bcopy(uint32_t *out, uint32_t *in);
40
41 static uint32_t dataout[64];
42
43 static uint32_t datain1[64] = {
44 0x55555500, 0x55555501, 0xaaaaaa02, 0xaaaaaa03,
45 0x55555504, 0x55555505, 0xaaaaaa06, 0xaaaaaa07,
46 0x55555508, 0x55555509, 0xaaaaaa0a, 0xaaaaaa0b,
47 0x5555550c, 0x5555550d, 0xaaaaaa0e, 0xaaaaaa0f,
48 0x55555510, 0x55555511, 0xaaaaaa12, 0xaaaaaa13,
49 0x55555514, 0x55555515, 0xaaaaaa16, 0xaaaaaa17,
50 0x55555518, 0x55555519, 0xaaaaaa1a, 0xaaaaaa1b,
51 0x5555551c, 0x5555551d, 0xaaaaaa1e, 0xaaaaaa1f,
52 0x55555520, 0x55555521, 0xaaaaaa22, 0xaaaaaa23,
53 0x55555524, 0x55555525, 0xaaaaaa26, 0xaaaaaa27,
54 0x55555528, 0x55555529, 0xaaaaaa2a, 0xaaaaaa2b,
55 0x5555552c, 0x5555552d, 0xaaaaaa2e, 0xaaaaaa2f,
56 0x55555530, 0x55555531, 0xaaaaaa32, 0xaaaaaa33,
57 0x55555534, 0x55555535, 0xaaaaaa36, 0xaaaaaa37,
58 0x55555538, 0x55555539, 0xaaaaaa3a, 0xaaaaaa3b,
59 0x5555553c, 0x5555553d, 0xaaaaaa3e, 0xaaaaaa3f
60 };
61
62 static uint32_t datain2[64] = {
63 0xaaaaaaff, 0xaaaaaafe, 0x555555fd, 0x555555fc,
64 0xaaaaaafb, 0xaaaaaafa, 0x555555f9, 0x555555f8,
65 0xaaaaaaf7, 0xaaaaaaf6, 0x555555f5, 0x555555f4,
66 0xaaaaaaf3, 0xaaaaaaf2, 0x555555f1, 0x555555f0,
67 0xaaaaaaef, 0xaaaaaaee, 0x555555ed, 0x555555ec,
68 0xaaaaaaeb, 0xaaaaaaea, 0x555555e9, 0x555555e8,
69 0xaaaaaae7, 0xaaaaaae6, 0x555555e5, 0x555555e4,
70 0xaaaaaae3, 0xaaaaaae2, 0x555555e1, 0x555555e0,
71 0xaaaaaadf, 0xaaaaaade, 0x555555dd, 0x555555dc,
72 0xaaaaaadb, 0xaaaaaada, 0x555555d9, 0x555555d8,
73 0xaaaaaad7, 0xaaaaaad6, 0x555555d5, 0x555555d4,
74 0xaaaaaad3, 0xaaaaaad2, 0x555555d1, 0x555555d0,
75 0xaaaaaacf, 0xaaaaaace, 0x555555cd, 0x555555cc,
76 0xaaaaaacb, 0xaaaaaaca, 0x555555c9, 0x555555c8,
77 0xaaaaaac7, 0xaaaaaac6, 0x555555c5, 0x555555c4,
78 0xaaaaaac3, 0xaaaaaac2, 0x555555c1, 0x555555c0
79 };
80
81 /*
82 * cbbcopy(int unit, struct fps_test_ereport *report)
83 * exercises block load and store path thru floating point
84 * registers. Returns whether load/store was successful.
85 * If an error, all relevant data is stored in report.
86 * Purpose: FRF integraty check thru both block ld/st and P$
87 * ax/ms pipe for health check online check utility. The utility is intented
88 * to detect simple stuck at fault not timing related faults.
89 */
90 int
cbbcopy(struct fps_test_ereport * report)91 cbbcopy(struct fps_test_ereport *report)
92 {
93 int i;
94 uint64_t expect;
95 uint64_t observe;
96
97 ax_bcopy(dataout, datain1);
98 asi_bcopy_f0(dataout, dataout);
99
100 for (i = 0; i < 64; i++) {
101 if (dataout[i] != datain1[i]) {
102 expect = (uint64_t)datain1[i];
103 observe = (uint64_t)dataout[i];
104 setup_fps_test_struct(NO_EREPORT_INFO, report,
105 6337, &observe, &expect, 1, 1);
106
107 return (FPU_FOROFFLINE);
108 }
109 }
110
111 ax_bcopy(dataout, datain2);
112 asi_bcopy_f16(dataout, dataout);
113
114 for (i = 0; i < 64; i++) {
115 if (dataout[i] != datain2[i]) {
116 expect = (uint64_t)datain2[i];
117 observe = (uint64_t)dataout[i];
118 setup_fps_test_struct(NO_EREPORT_INFO, report,
119 6338, &observe, &expect, 1, 1);
120
121 return (FPU_FOROFFLINE);
122 }
123 }
124
125 return (FPU_OK);
126 }
127
128 /*
129 * asi_bcopy_f0(uint32_t *out, uint32_t *in)
130 * does the assembly load/store of in to out
131 */
132 /* ARGSUSED */
133 static void
asi_bcopy_f0(uint32_t * out,uint32_t * in)134 asi_bcopy_f0(uint32_t *out, uint32_t *in)
135 {
136 asm("ldda [%i1]0xf8,%f0");
137 asm("membar #Sync");
138 asm("stda %f0,[%i0]0xf0");
139 asm("membar #Sync");
140 }
141
142 /*
143 * asi_bcopy_f16(uint32_t *out, uint32_t *in)
144 * does the assembly load/store of in to out
145 */
146 /* ARGSUSED */
147 static void
asi_bcopy_f16(uint32_t * out,uint32_t * in)148 asi_bcopy_f16(uint32_t *out, uint32_t *in)
149 {
150 asm("ldda [%i1]0xf0,%f16");
151 asm("membar #Sync");
152 asm("stda %f16,[%i0]0xf8");
153 asm("membar #Sync");
154 }
155
156 /*
157 * ax_bcopy(uint32_t *out, uint32_t *in)
158 * does the assembly load/store of in to out
159 */
160 /* ARGSUSED */
161 static void
ax_bcopy(uint32_t * out,uint32_t * in)162 ax_bcopy(uint32_t *out, uint32_t *in)
163 {
164 asm("prefetch [%i1],21");
165 asm("prefetch [%i1+0x40],21");
166 asm("ldd [%i1],%f16");
167 asm("ldd [%i1+8],%f18");
168 asm("ldd [%i1+0x10],%f20");
169 asm("ldd [%i1+0x18],%f22");
170 asm("ldd [%i1+0x20],%f24");
171 asm("ldd [%i1+0x28],%f26");
172 asm("ldd [%i1+0x30],%f28");
173 asm("ldd [%i1+0x38],%f30");
174 asm("ldd [%i1+0x40],%f32");
175
176 asm("prefetch [%i1+0x80],21");
177 asm("ldd [%i1+0x48],%f34");
178 asm("ldd [%i1+0x50],%f36");
179 asm("ldd [%i1+0x58],%f38");
180 asm("ldd [%i1+0x60],%f40");
181 asm("ldd [%i1+0x68],%f42");
182 asm("ldd [%i1+0x70],%f44");
183 asm("ldd [%i1+0x78],%f46");
184
185 asm("prefetch [%i1+0xc0],21");
186 asm("ldd [%i1+0x80],%f0");
187 asm("ldd [%i1+0x88],%f2");
188 asm("ldd [%i1+0x90],%f4");
189 asm("ldd [%i1+0x98],%f6");
190 asm("ldd [%i1+0xa0],%f8");
191 asm("ldd [%i1+0xa8],%f10");
192 asm("ldd [%i1+0xb0],%f12");
193 asm("ldd [%i1+0xb8],%f14");
194
195 asm("ldd [%i1+0xc0],%f48");
196 asm("ldd [%i1+0xc8],%f50");
197 asm("ldd [%i1+0xd0],%f52");
198 asm("ldd [%i1+0xd8],%f54");
199 asm("ldd [%i1+0xe0],%f56");
200 asm("ldd [%i1+0xe8],%f58");
201 asm("ldd [%i1+0xf0],%f60");
202 asm("ldd [%i1+0xf8],%f62");
203
204 asm("membar #Sync");
205 asm("stda %f16,[%i0]0xf8");
206 asm("add %i0,0x40,%i0");
207 asm("stda %f32,[%i0]0xf0");
208 asm("add %i0,0x40,%i0");
209 asm("stda %f0,[%i0]0xf0");
210 asm("add %i0,0x40,%i0");
211 asm("stda %f48,[%i0]0xf0");
212 asm("membar #Sync");
213 }
214