Author: jhibbits
Date: Sat Mar 23 03:23:20 2019
New Revision: 345435
URL: https://svnweb.freebsd.org/changeset/base/345435

Log:
  powernv: Add Hypervisor Maintenance Interrupt handler
  
  Attempting to build www/firefox on POWER9 resulted in a HMI exception being
  thrown, a fatal trap currently.  This is typically caused by timer facility
  errors, but examination of the Hypervisor Maintenance Exception Register
  (HMER) yielded only that an exception had recovered, with no information of
  the actual exception cause.
  
  When an HMI occurs, OPAL_HANDLE_HMI or OPAL_HANDLE_HMI2 must be called to
  handle the exception at the firmware level.  If the exception is handled, we
  can continue.
  
  This adds only the preliminary handler, enough to prevent package building
  from panicking.  An enhancement in the future is to use the flags returned
  by OPAL_HANDLE_HMI2 to print more useful error messages, and log maintenance
  events.
  
  Reviewed by:  luporl
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D19634

Added:
  head/sys/powerpc/powernv/opal_hmi.c   (contents, props changed)
Modified:
  head/sys/conf/files.powerpc
  head/sys/powerpc/include/spr.h
  head/sys/powerpc/include/trap.h
  head/sys/powerpc/powernv/opal.h
  head/sys/powerpc/powerpc/interrupt.c

Modified: head/sys/conf/files.powerpc
==============================================================================
--- head/sys/conf/files.powerpc Sat Mar 23 03:10:23 2019        (r345434)
+++ head/sys/conf/files.powerpc Sat Mar 23 03:23:20 2019        (r345435)
@@ -192,6 +192,7 @@ powerpc/powernv/opal_async.c        optional        powernv
 powerpc/powernv/opal_console.c optional        powernv
 powerpc/powernv/opal_dev.c     optional        powernv
 powerpc/powernv/opal_flash.c   optional        powernv
+powerpc/powernv/opal_hmi.c     optional        powernv
 powerpc/powernv/opal_i2c.c     optional        iicbus fdt powernv
 powerpc/powernv/opal_i2cm.c    optional        iicbus fdt powernv
 powerpc/powernv/opal_pci.c     optional        powernv pci

Modified: head/sys/powerpc/include/spr.h
==============================================================================
--- head/sys/powerpc/include/spr.h      Sat Mar 23 03:10:23 2019        
(r345434)
+++ head/sys/powerpc/include/spr.h      Sat Mar 23 03:23:20 2019        
(r345435)
@@ -242,6 +242,8 @@
 #define          LPCR_PECE_ME            (1ULL << 12) /* Machine Check and 
Hypervisor */
                                                /* Maintenance exceptions */
 #define        SPR_LPID                0x13f   /* Logical Partitioning Control 
*/
+#define        SPR_HMER                0x150   /* Hypervisor Maintenance 
Exception Register */
+#define        SPR_HMEER               0x151   /* Hypervisor Maintenance 
Exception Enable Register */
 
 #define        SPR_PTCR                0x1d0   /* Partition Table Control 
Register */
 #define        SPR_SPEFSCR             0x200   /* ..8 Signal Processing Engine 
FSCR. */

Modified: head/sys/powerpc/include/trap.h
==============================================================================
--- head/sys/powerpc/include/trap.h     Sat Mar 23 03:10:23 2019        
(r345434)
+++ head/sys/powerpc/include/trap.h     Sat Mar 23 03:23:20 2019        
(r345435)
@@ -153,6 +153,7 @@
 #ifndef LOCORE
 struct trapframe;
 struct pcb;
+extern int     (*hmi_handler)(struct trapframe *);
 void    trap(struct trapframe *);
 int    ppc_instr_emulate(struct trapframe *, struct pcb *);
 #endif

Modified: head/sys/powerpc/powernv/opal.h
==============================================================================
--- head/sys/powerpc/powernv/opal.h     Sat Mar 23 03:10:23 2019        
(r345434)
+++ head/sys/powerpc/powernv/opal.h     Sat Mar 23 03:23:20 2019        
(r345435)
@@ -71,8 +71,10 @@ int opal_call(uint64_t token, ...);
 #define        OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45
 #define        OPAL_RETURN_CPU                 69
 #define        OPAL_REINIT_CPUS                70
+#define        OPAL_CHECK_TOKEN                80
 #define        OPAL_CHECK_ASYNC_COMPLETION     86
 #define        OPAL_SENSOR_READ                88
+#define        OPAL_HANDLE_HMI                 98
 #define        OPAL_IPMI_SEND                  107
 #define        OPAL_IPMI_RECV                  108
 #define        OPAL_I2C_REQUEST                109
@@ -102,6 +104,7 @@ int opal_call(uint64_t token, ...);
 #define        OPAL_SENSOR_GROUP_CLEAR         156
 #define        OPAL_SENSOR_READ_U64            162
 #define        OPAL_SENSOR_GROUP_ENABLE        163
+#define        OPAL_HANDLE_HMI2                166
 
 /* For OPAL_PCI_SET_PE */
 #define        OPAL_UNMAP_PE                   0
@@ -133,6 +136,15 @@ int opal_call(uint64_t token, ...);
 #define        OPAL_EMPTY                      -16
 #define        OPAL_XIVE_PROVISIONING          -31
 #define        OPAL_XIVE_FREE_ACTIVE           -32
+
+#define        OPAL_TOKEN_ABSENT               0
+#define        OPAL_TOKEN_PRESENT              1
+
+#define        OPAL_HMI_FLAGS_TB_RESYNC        (1ull << 0)
+#define        OPAL_HMI_FLAGS_DEC_LOST         (1ull << 1)
+#define        OPAL_HMI_FLAGS_HDEC_LOST        (1ull << 2)
+#define        OPAL_HMI_FLAGS_TOD_TB_FAIL      (1ull << 3)
+#define        OPAL_HMI_FLAGS_NEW_EVENT        (1ull << 63)
 
 #define        OPAL_XIVE_XICS_MODE_EMU 0
 #define        OPAL_XIVE_XICS_MODE_EXP 1

Added: head/sys/powerpc/powernv/opal_hmi.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/powerpc/powernv/opal_hmi.c Sat Mar 23 03:23:20 2019        
(r345435)
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2019 Justin Hibbits
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/spr.h>
+#include <machine/trap.h>
+#include "opal.h"
+
+static int
+opal_hmi_handler2(struct trapframe *frame)
+{
+       int64_t flags;
+       int err;
+
+       err = opal_call(OPAL_HANDLE_HMI2, vtophys(&flags));
+
+       /* XXX: At some point, handle the flags outvar. */
+       if (err == OPAL_SUCCESS) {
+               mtspr(SPR_HMER, 0);
+               return (0);
+       }
+
+       printf("HMI handler failed!  OPAL error code: %d\n", err);
+
+       return (-1);
+}
+
+static int
+opal_hmi_handler(struct trapframe *frame)
+{
+       int err;
+
+       err = opal_call(OPAL_HANDLE_HMI);
+
+       if (err == OPAL_SUCCESS) {
+               mtspr(SPR_HMER, 0);
+               return (0);
+       }
+
+       printf("HMI handler failed!  OPAL error code: %d\n", err);
+
+       return (-1);
+}
+
+static void
+opal_setup_hmi(void *data)
+{
+       /* This only works for OPAL, so first make sure we have it. */
+       if (opal_check() != 0)
+               return;
+
+       if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI2) == OPAL_TOKEN_PRESENT)
+               hmi_handler = opal_hmi_handler2;
+       else if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI) == 
OPAL_TOKEN_PRESENT)
+               hmi_handler = opal_hmi_handler;
+       else {
+               printf("Warning: No OPAL HMI handler found.\n");
+               return;
+       }
+
+       if (bootverbose)
+               printf("Installed OPAL HMI handler.\n");
+}
+
+SYSINIT(opal_setup_hmi, SI_SUB_HYPERVISOR, SI_ORDER_ANY, opal_setup_hmi, NULL);

Modified: head/sys/powerpc/powerpc/interrupt.c
==============================================================================
--- head/sys/powerpc/powerpc/interrupt.c        Sat Mar 23 03:10:23 2019        
(r345434)
+++ head/sys/powerpc/powerpc/interrupt.c        Sat Mar 23 03:23:20 2019        
(r345435)
@@ -32,6 +32,7 @@
  */
 
 #include "opt_hwpmc_hooks.h"
+#include "opt_platform.h"
 
 #include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
 
@@ -68,6 +69,10 @@
 
 #include "pic_if.h"
 
+#ifdef POWERNV
+int (*hmi_handler)(struct trapframe *);
+#endif
+
 /*
  * A very short dispatch, to try and maximise assembler code use
  * between all exception types. Maybe 'true' interrupts should go
@@ -117,6 +122,13 @@ powerpc_interrupt(struct trapframe *framep)
                        pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, 
framep);
                critical_exit();
                break;
+#endif
+
+#ifdef POWERNV
+       case EXC_HMI:
+               if (hmi_handler != 0 && hmi_handler(framep) == 0)
+                       break;
+               /* If no handler, or failure to handle, just drop to trap. */
 #endif
 
        default:
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to