1*578d9a56SPatrick Mooney /*
2*578d9a56SPatrick Mooney  * This file and its contents are supplied under the terms of the
3*578d9a56SPatrick Mooney  * Common Development and Distribution License ("CDDL"), version 1.0.
4*578d9a56SPatrick Mooney  * You may only use this file in accordance with the terms of version
5*578d9a56SPatrick Mooney  * 1.0 of the CDDL.
6*578d9a56SPatrick Mooney  *
7*578d9a56SPatrick Mooney  * A full copy of the text of the CDDL should have accompanied this
8*578d9a56SPatrick Mooney  * source.  A copy of the CDDL is also available via the Internet at
9*578d9a56SPatrick Mooney  * http://www.illumos.org/license/CDDL.
10*578d9a56SPatrick Mooney  */
11*578d9a56SPatrick Mooney 
12*578d9a56SPatrick Mooney /*
13*578d9a56SPatrick Mooney  * Copyright 2022 Oxide Computer Company
14*578d9a56SPatrick Mooney  */
15*578d9a56SPatrick Mooney 
16*578d9a56SPatrick Mooney #include "payload_common.h"
17*578d9a56SPatrick Mooney #include "payload_utils.h"
18*578d9a56SPatrick Mooney 
19*578d9a56SPatrick Mooney int
leaf_cmp(const uint32_t * a,const uint32_t * b)20*578d9a56SPatrick Mooney leaf_cmp(const uint32_t *a, const uint32_t *b)
21*578d9a56SPatrick Mooney {
22*578d9a56SPatrick Mooney 	return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]);
23*578d9a56SPatrick Mooney }
24*578d9a56SPatrick Mooney 
25*578d9a56SPatrick Mooney const uint32_t expected_base[] = { 5, 0x74737552, 0x65646978, 0x4f206465 };
26*578d9a56SPatrick Mooney 
27*578d9a56SPatrick Mooney struct test_case {
28*578d9a56SPatrick Mooney 	uint32_t func;
29*578d9a56SPatrick Mooney 	uint32_t idx;
30*578d9a56SPatrick Mooney 	uint32_t val_eax;
31*578d9a56SPatrick Mooney 	int fallback;
32*578d9a56SPatrick Mooney };
33*578d9a56SPatrick Mooney 
34*578d9a56SPatrick Mooney const struct test_case cases[] = {
35*578d9a56SPatrick Mooney 	/* basic leaf match */
36*578d9a56SPatrick Mooney 	{
37*578d9a56SPatrick Mooney 		.func = 1,
38*578d9a56SPatrick Mooney 		.val_eax = 0x100,
39*578d9a56SPatrick Mooney 	},
40*578d9a56SPatrick Mooney 	/* index matching */
41*578d9a56SPatrick Mooney 	{
42*578d9a56SPatrick Mooney 		.func = 3,
43*578d9a56SPatrick Mooney 		.idx = 0,
44*578d9a56SPatrick Mooney 		.val_eax = 0x300,
45*578d9a56SPatrick Mooney 	},
46*578d9a56SPatrick Mooney 	{
47*578d9a56SPatrick Mooney 		.func = 3,
48*578d9a56SPatrick Mooney 		.idx = 1,
49*578d9a56SPatrick Mooney 		.val_eax = 0x301,
50*578d9a56SPatrick Mooney 	},
51*578d9a56SPatrick Mooney 	/* leaf match with hole */
52*578d9a56SPatrick Mooney 	{
53*578d9a56SPatrick Mooney 		.func = 4,
54*578d9a56SPatrick Mooney 		.idx = 0,
55*578d9a56SPatrick Mooney 		.val_eax = 0x400,
56*578d9a56SPatrick Mooney 	},
57*578d9a56SPatrick Mooney 	{
58*578d9a56SPatrick Mooney 		.func = 4,
59*578d9a56SPatrick Mooney 		.idx = 2,
60*578d9a56SPatrick Mooney 		.val_eax = 0x402,
61*578d9a56SPatrick Mooney 	},
62*578d9a56SPatrick Mooney 	/* last std leaf */
63*578d9a56SPatrick Mooney 	{
64*578d9a56SPatrick Mooney 		.func = 5,
65*578d9a56SPatrick Mooney 		.val_eax = 0x5,
66*578d9a56SPatrick Mooney 	},
67*578d9a56SPatrick Mooney 
68*578d9a56SPatrick Mooney 	/* invalid leaf */
69*578d9a56SPatrick Mooney 	{
70*578d9a56SPatrick Mooney 		.func = 2,
71*578d9a56SPatrick Mooney 		.val_eax = 0,
72*578d9a56SPatrick Mooney 	},
73*578d9a56SPatrick Mooney 	/* invalid index */
74*578d9a56SPatrick Mooney 	{
75*578d9a56SPatrick Mooney 		.func = 3,
76*578d9a56SPatrick Mooney 		.idx = 2,
77*578d9a56SPatrick Mooney 		.val_eax = 0,
78*578d9a56SPatrick Mooney 	},
79*578d9a56SPatrick Mooney 	{
80*578d9a56SPatrick Mooney 		.func = 4,
81*578d9a56SPatrick Mooney 		.idx = 1,
82*578d9a56SPatrick Mooney 		.val_eax = 0x0,
83*578d9a56SPatrick Mooney 	},
84*578d9a56SPatrick Mooney 	{
85*578d9a56SPatrick Mooney 		.func = 4,
86*578d9a56SPatrick Mooney 		.idx = 0xffff,
87*578d9a56SPatrick Mooney 		.val_eax = 0x0,
88*578d9a56SPatrick Mooney 	},
89*578d9a56SPatrick Mooney 
90*578d9a56SPatrick Mooney 	/* basic extd leaf match */
91*578d9a56SPatrick Mooney 	{
92*578d9a56SPatrick Mooney 		.func = 0x80000000,
93*578d9a56SPatrick Mooney 		.val_eax = 0x80000001,
94*578d9a56SPatrick Mooney 	},
95*578d9a56SPatrick Mooney 	/* basic extd index match */
96*578d9a56SPatrick Mooney 	{
97*578d9a56SPatrick Mooney 		.func = 0x80000001,
98*578d9a56SPatrick Mooney 		.idx = 0,
99*578d9a56SPatrick Mooney 		.val_eax = 0x8000,
100*578d9a56SPatrick Mooney 	},
101*578d9a56SPatrick Mooney 	{
102*578d9a56SPatrick Mooney 		.func = 0x80000001,
103*578d9a56SPatrick Mooney 		.idx = 1,
104*578d9a56SPatrick Mooney 		.val_eax = 0x8001,
105*578d9a56SPatrick Mooney 	},
106*578d9a56SPatrick Mooney 	/* zeroed for invalid index */
107*578d9a56SPatrick Mooney 	{
108*578d9a56SPatrick Mooney 		.func = 0x80000001,
109*578d9a56SPatrick Mooney 		.idx = 5,
110*578d9a56SPatrick Mooney 		.val_eax = 0,
111*578d9a56SPatrick Mooney 	},
112*578d9a56SPatrick Mooney 
113*578d9a56SPatrick Mooney 	/* fallback beyond std leaf */
114*578d9a56SPatrick Mooney 	{
115*578d9a56SPatrick Mooney 		.func = 6,
116*578d9a56SPatrick Mooney 		.fallback = 1,
117*578d9a56SPatrick Mooney 	},
118*578d9a56SPatrick Mooney 	/* fallback beyond extd leaf */
119*578d9a56SPatrick Mooney 	{
120*578d9a56SPatrick Mooney 		.func = 0x80000002,
121*578d9a56SPatrick Mooney 		.fallback = 1,
122*578d9a56SPatrick Mooney 	},
123*578d9a56SPatrick Mooney };
124*578d9a56SPatrick Mooney #define	NCASES	(sizeof (cases) / sizeof (cases[0]))
125*578d9a56SPatrick Mooney 
126*578d9a56SPatrick Mooney void
do_test(int intel_fallback)127*578d9a56SPatrick Mooney do_test(int intel_fallback)
128*578d9a56SPatrick Mooney {
129*578d9a56SPatrick Mooney 	uint32_t regs[4];
130*578d9a56SPatrick Mooney 	uint32_t expected_fallback[4] = { 0 };
131*578d9a56SPatrick Mooney 
132*578d9a56SPatrick Mooney 	cpuid(0, 0, regs);
133*578d9a56SPatrick Mooney 	if (!leaf_cmp(regs, expected_base)) {
134*578d9a56SPatrick Mooney 		outb(IOP_TEST_RESULT, TEST_RESULT_FAIL);
135*578d9a56SPatrick Mooney 	}
136*578d9a56SPatrick Mooney 
137*578d9a56SPatrick Mooney 	if (intel_fallback) {
138*578d9a56SPatrick Mooney 		cpuid(regs[0], 0, expected_fallback);
139*578d9a56SPatrick Mooney 	}
140*578d9a56SPatrick Mooney 
141*578d9a56SPatrick Mooney 	for (uint_t i = 0; i < NCASES; i++) {
142*578d9a56SPatrick Mooney 		cpuid(cases[i].func, cases[i].idx, regs);
143*578d9a56SPatrick Mooney 		if (cases[i].fallback != 0) {
144*578d9a56SPatrick Mooney 			if (!leaf_cmp(regs, expected_fallback)) {
145*578d9a56SPatrick Mooney 				outb(IOP_TEST_RESULT, TEST_RESULT_FAIL);
146*578d9a56SPatrick Mooney 			}
147*578d9a56SPatrick Mooney 		} else {
148*578d9a56SPatrick Mooney 			if (regs[0] != cases[i].val_eax) {
149*578d9a56SPatrick Mooney 				outb(IOP_TEST_RESULT, TEST_RESULT_FAIL);
150*578d9a56SPatrick Mooney 			}
151*578d9a56SPatrick Mooney 		}
152*578d9a56SPatrick Mooney 	}
153*578d9a56SPatrick Mooney }
154*578d9a56SPatrick Mooney 
155*578d9a56SPatrick Mooney void
start(void)156*578d9a56SPatrick Mooney start(void)
157*578d9a56SPatrick Mooney {
158*578d9a56SPatrick Mooney 	/* Check results expecting Intel-style fallback */
159*578d9a56SPatrick Mooney 	do_test(1);
160*578d9a56SPatrick Mooney 
161*578d9a56SPatrick Mooney 	/* Notify userspace component to change fallback style */
162*578d9a56SPatrick Mooney 	outl(IOP_TEST_VALUE, 0);
163*578d9a56SPatrick Mooney 
164*578d9a56SPatrick Mooney 	/* Check results expecting AMD-style fallback */
165*578d9a56SPatrick Mooney 	do_test(0);
166*578d9a56SPatrick Mooney 
167*578d9a56SPatrick Mooney 	/* If all is well by this point, indicate success */
168*578d9a56SPatrick Mooney 	outb(IOP_TEST_RESULT, TEST_RESULT_PASS);
169*578d9a56SPatrick Mooney }
170