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