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