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 #include "test_defs.h" 19 20 #define MSR_APICBASE 0x1b 21 #define MSR_X2APIC_BASE 0x800 22 #define MSR_X2APIC_MAX 0x8ff 23 24 #define APICBASE_X2APIC (1 << 10) 25 26 static bool 27 reg_readable(uint32_t reg) 28 { 29 switch (reg) { 30 case 0x802: /* ID */ 31 case 0x803: /* VER */ 32 33 case 0x808: /* TPR */ 34 case 0x809: /* APR */ 35 case 0x80a: /* PPR */ 36 37 case 0x80c: /* RRR */ 38 case 0x80d: /* LDR */ 39 case 0x80e: /* DFR */ 40 case 0x80f: /* SVR */ 41 42 case 0x810 ... 0x817: /* ISR */ 43 case 0x818 ... 0x81f: /* TMR */ 44 case 0x820 ... 0x827: /* IRR */ 45 46 case 0x828: /* ESR */ 47 48 case 0x82f: /* LVT_CMCI */ 49 case 0x830: /* ICR */ 50 51 case 0x832: /* LVT_TIMER */ 52 case 0x833: /* LVT_THERMAL */ 53 case 0x834: /* LVT_PERF */ 54 case 0x835: /* LVT_LINT0 */ 55 case 0x836: /* LVT_LINT1 */ 56 case 0x837: /* LVT_ERROR */ 57 case 0x838: /* TIMER_ICR */ 58 case 0x839: /* TIMER_CCR */ 59 60 case 0x83e: /* TIMER_DCR */ 61 return (true); 62 default: 63 return (false); 64 } 65 } 66 67 static bool 68 reg_writable(uint32_t reg) 69 { 70 switch (reg) { 71 case 0x802: /* ID */ 72 73 case 0x808: /* TPR */ 74 75 case 0x80b: /* EOI */ 76 77 case 0x80d: /* LDR */ 78 case 0x80e: /* DFR */ 79 case 0x80f: /* SVR */ 80 81 case 0x828: /* ESR */ 82 83 case 0x82f: /* LVT_CMCI */ 84 case 0x830: /* ICR */ 85 86 case 0x832: /* LVT_TIMER */ 87 case 0x833: /* LVT_THERMAL */ 88 case 0x834: /* LVT_PERF */ 89 case 0x835: /* LVT_LINT0 */ 90 case 0x836: /* LVT_LINT1 */ 91 case 0x837: /* LVT_ERROR */ 92 case 0x838: /* TIMER_ICR */ 93 94 case 0x83e: /* TIMER_DCR */ 95 case 0x83f: /* SELF_IPI */ 96 return (true); 97 default: 98 return (false); 99 } 100 } 101 102 void 103 start(void) 104 { 105 uint64_t base = rdmsr(MSR_APICBASE); 106 if ((base & APICBASE_X2APIC) == 0) { 107 /* bail if the host has not enabled x2apic for us */ 108 outb(IOP_TEST_RESULT, TEST_RESULT_FAIL); 109 } 110 111 for (uint32_t msr = MSR_X2APIC_BASE; msr <= MSR_X2APIC_MAX; msr++) { 112 uint64_t val = 0; 113 114 if (reg_readable(msr)) { 115 val = rdmsr(msr); 116 } 117 118 if (reg_writable(msr)) { 119 if (msr == 0x828) { 120 /* 121 * While the LAPIC is in x2APIC mode, writes to 122 * the ESR must carry a value of 0. 123 */ 124 val = 0; 125 } 126 wrmsr(msr, val); 127 } 128 } 129 130 /* If we made it this far without a #GP, it counts as a win */ 131 outb(IOP_TEST_RESULT, TEST_RESULT_PASS); 132 } 133