18af4cc4dSJustin Hibbits /*- 28af4cc4dSJustin Hibbits * Copyright (c) 2019 Justin Hibbits 38af4cc4dSJustin Hibbits * 48af4cc4dSJustin Hibbits * Redistribution and use in source and binary forms, with or without 58af4cc4dSJustin Hibbits * modification, are permitted provided that the following conditions 68af4cc4dSJustin Hibbits * are met: 78af4cc4dSJustin Hibbits * 88af4cc4dSJustin Hibbits * 1. Redistributions of source code must retain the above copyright 98af4cc4dSJustin Hibbits * notice, this list of conditions and the following disclaimer. 108af4cc4dSJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 118af4cc4dSJustin Hibbits * notice, this list of conditions and the following disclaimer in the 128af4cc4dSJustin Hibbits * documentation and/or other materials provided with the distribution. 138af4cc4dSJustin Hibbits * 148af4cc4dSJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 158af4cc4dSJustin Hibbits * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 168af4cc4dSJustin Hibbits * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 178af4cc4dSJustin Hibbits * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 188af4cc4dSJustin Hibbits * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 198af4cc4dSJustin Hibbits * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 208af4cc4dSJustin Hibbits * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 218af4cc4dSJustin Hibbits * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228af4cc4dSJustin Hibbits * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 238af4cc4dSJustin Hibbits * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248af4cc4dSJustin Hibbits */ 258af4cc4dSJustin Hibbits 268af4cc4dSJustin Hibbits #include <sys/cdefs.h> 278af4cc4dSJustin Hibbits __FBSDID("$FreeBSD$"); 288af4cc4dSJustin Hibbits 298af4cc4dSJustin Hibbits #include <sys/param.h> 308af4cc4dSJustin Hibbits #include <sys/types.h> 31fdb916d5SJustin Hibbits #include <sys/eventhandler.h> 328af4cc4dSJustin Hibbits #include <sys/kernel.h> 338af4cc4dSJustin Hibbits #include <sys/systm.h> 34fdb916d5SJustin Hibbits #include <sys/endian.h> 358af4cc4dSJustin Hibbits 368af4cc4dSJustin Hibbits #include <vm/vm.h> 378af4cc4dSJustin Hibbits #include <vm/pmap.h> 388af4cc4dSJustin Hibbits 398af4cc4dSJustin Hibbits #include <machine/spr.h> 408af4cc4dSJustin Hibbits #include <machine/trap.h> 418af4cc4dSJustin Hibbits #include "opal.h" 428af4cc4dSJustin Hibbits 43fdb916d5SJustin Hibbits struct opal_hmi_event { 44fdb916d5SJustin Hibbits uint8_t version; 45fdb916d5SJustin Hibbits uint8_t severity; 46fdb916d5SJustin Hibbits uint8_t type; 47fdb916d5SJustin Hibbits uint8_t disposition; 48fdb916d5SJustin Hibbits uint8_t rsvd_1[4]; 49fdb916d5SJustin Hibbits uint64_t hmer; 50fdb916d5SJustin Hibbits uint64_t tfmr; 51fdb916d5SJustin Hibbits union { 52fdb916d5SJustin Hibbits struct { 53fdb916d5SJustin Hibbits uint8_t xstop_type; 54fdb916d5SJustin Hibbits uint8_t rsvd_2[3]; 55fdb916d5SJustin Hibbits uint32_t xstop_reason; 56fdb916d5SJustin Hibbits union { 57fdb916d5SJustin Hibbits uint32_t pir; 58fdb916d5SJustin Hibbits uint32_t chip_id; 59fdb916d5SJustin Hibbits }; 60fdb916d5SJustin Hibbits }; 61fdb916d5SJustin Hibbits }; 62fdb916d5SJustin Hibbits }; 63fdb916d5SJustin Hibbits 64fdb916d5SJustin Hibbits #define HMI_DISP_RECOVERED 0 65fdb916d5SJustin Hibbits #define HMI_DISP_NOT_RECOVERED 1 66fdb916d5SJustin Hibbits 67fdb916d5SJustin Hibbits static void 68fdb916d5SJustin Hibbits opal_hmi_event_handler(void *unused, struct opal_msg *msg) 69fdb916d5SJustin Hibbits { 70fdb916d5SJustin Hibbits struct opal_hmi_event evt; 71fdb916d5SJustin Hibbits 72fdb916d5SJustin Hibbits memcpy(&evt, &msg->params, sizeof(evt)); 73fdb916d5SJustin Hibbits printf("Hypervisor Maintenance Event received" 74fdb916d5SJustin Hibbits "(Severity %d, type %d, HMER: %016lx).\n", 75fdb916d5SJustin Hibbits evt.severity, evt.type, evt.hmer); 76fdb916d5SJustin Hibbits 77fdb916d5SJustin Hibbits if (evt.disposition == HMI_DISP_NOT_RECOVERED) 78fdb916d5SJustin Hibbits panic("Unrecoverable hypervisor maintenance exception on CPU %d", 79fdb916d5SJustin Hibbits evt.pir); 80fdb916d5SJustin Hibbits 81fdb916d5SJustin Hibbits return; 82fdb916d5SJustin Hibbits } 83fdb916d5SJustin Hibbits 848af4cc4dSJustin Hibbits static int 85*1c56203bSJustin Hibbits opal_hmi_handler2(struct trapframe *frame) 86*1c56203bSJustin Hibbits { 87*1c56203bSJustin Hibbits uint64_t flags; 88*1c56203bSJustin Hibbits int err; 89*1c56203bSJustin Hibbits 90*1c56203bSJustin Hibbits flags = 0; 91*1c56203bSJustin Hibbits err = opal_call(OPAL_HANDLE_HMI2, vtophys(&flags)); 92*1c56203bSJustin Hibbits 93*1c56203bSJustin Hibbits if (flags & OPAL_HMI_FLAGS_TOD_TB_FAIL) 94*1c56203bSJustin Hibbits panic("TOD/TB recovery failure"); 95*1c56203bSJustin Hibbits 96*1c56203bSJustin Hibbits if (err == OPAL_SUCCESS) 97*1c56203bSJustin Hibbits return (0); 98*1c56203bSJustin Hibbits 99*1c56203bSJustin Hibbits printf("HMI handler failed! OPAL error code: %d\n", err); 100*1c56203bSJustin Hibbits 101*1c56203bSJustin Hibbits return (-1); 102*1c56203bSJustin Hibbits } 103*1c56203bSJustin Hibbits 104*1c56203bSJustin Hibbits static int 1058af4cc4dSJustin Hibbits opal_hmi_handler(struct trapframe *frame) 1068af4cc4dSJustin Hibbits { 1078af4cc4dSJustin Hibbits int err; 1088af4cc4dSJustin Hibbits 1098af4cc4dSJustin Hibbits err = opal_call(OPAL_HANDLE_HMI); 1108af4cc4dSJustin Hibbits 111*1c56203bSJustin Hibbits if (err == OPAL_SUCCESS) 1128af4cc4dSJustin Hibbits return (0); 1138af4cc4dSJustin Hibbits 1148af4cc4dSJustin Hibbits printf("HMI handler failed! OPAL error code: %d\n", err); 1158af4cc4dSJustin Hibbits 1168af4cc4dSJustin Hibbits return (-1); 1178af4cc4dSJustin Hibbits } 1188af4cc4dSJustin Hibbits 1198af4cc4dSJustin Hibbits static void 1208af4cc4dSJustin Hibbits opal_setup_hmi(void *data) 1218af4cc4dSJustin Hibbits { 1228af4cc4dSJustin Hibbits /* This only works for OPAL, so first make sure we have it. */ 1238af4cc4dSJustin Hibbits if (opal_check() != 0) 1248af4cc4dSJustin Hibbits return; 1258af4cc4dSJustin Hibbits 126*1c56203bSJustin Hibbits if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI2) == OPAL_TOKEN_PRESENT) 127*1c56203bSJustin Hibbits hmi_handler = opal_hmi_handler2; 128*1c56203bSJustin Hibbits else if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI) == OPAL_TOKEN_PRESENT) 1298af4cc4dSJustin Hibbits hmi_handler = opal_hmi_handler; 1308af4cc4dSJustin Hibbits else { 1318af4cc4dSJustin Hibbits printf("Warning: No OPAL HMI handler found.\n"); 1328af4cc4dSJustin Hibbits return; 1338af4cc4dSJustin Hibbits } 1348af4cc4dSJustin Hibbits 135fdb916d5SJustin Hibbits EVENTHANDLER_REGISTER(OPAL_HMI_EVT, opal_hmi_event_handler, NULL, 136fdb916d5SJustin Hibbits EVENTHANDLER_PRI_ANY); 137fdb916d5SJustin Hibbits 1388af4cc4dSJustin Hibbits if (bootverbose) 1398af4cc4dSJustin Hibbits printf("Installed OPAL HMI handler.\n"); 1408af4cc4dSJustin Hibbits } 1418af4cc4dSJustin Hibbits 142fdb916d5SJustin Hibbits SYSINIT(opal_setup_hmi, SI_SUB_CPU, SI_ORDER_ANY, opal_setup_hmi, NULL); 143