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 22 #define APICBASE_X2APIC (1 << 10) 23 24 25 static void 26 write_vlapic(uint_t reg, uint32_t value) 27 { 28 volatile uint32_t *ptr = (uint32_t *)(MMIO_LAPIC_BASE + reg); 29 *ptr = value; 30 } 31 32 static uint32_t 33 read_vlapic(uint_t reg) 34 { 35 volatile uint32_t *ptr = (uint32_t *)(MMIO_LAPIC_BASE + reg); 36 return (*ptr); 37 } 38 39 static void 40 barrier(void) 41 { 42 asm volatile("": : :"memory"); 43 } 44 45 void 46 start(void) 47 { 48 uint64_t base = rdmsr(MSR_APICBASE); 49 if ((base & APICBASE_X2APIC) != 0) { 50 /* bail if the host has enabled x2apic for us */ 51 outb(IOP_TEST_RESULT, TEST_RESULT_FAIL); 52 } 53 54 /* Access the "normal" register offsets */ 55 for (uint_t reg = 0; reg < 0x1000; reg += 16) { 56 uint32_t val; 57 58 /* 59 * This ignores the fact that some register offsets are reserved 60 * (such as 0x3a0-0x3d0 and 0x3f0-0xff0) while others may be 61 * read-only or write-only. For the time being, we know that 62 * the emulation in bhyve will not emit errors or faults for 63 * such indiscretions committed via MMIO. 64 */ 65 val = read_vlapic(reg); 66 write_vlapic(reg, val); 67 } 68 69 /* 70 * Scan through byte-wise, even though such behavior is undefined as far 71 * as a to-specification LAPIC is concerned. 72 */ 73 for (uint_t off = 0; off < 0x1000; off++) { 74 volatile uint8_t *ptr = (uint8_t *)(MMIO_LAPIC_BASE + off); 75 76 uint8_t val; 77 78 val = *ptr; 79 barrier(); 80 *ptr = val; 81 } 82 83 /* If we made it this far without an exception, it is a win */ 84 outb(IOP_TEST_RESULT, TEST_RESULT_PASS); 85 } 86