Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Mar 2019 03:23:20 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345435 - in head/sys: conf powerpc/include powerpc/powernv powerpc/powerpc
Message-ID:  <201903230323.x2N3NKCo068847@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903230323.x2N3NKCo068847>