svn commit: r342108 - in head: share/man/man9 sys/contrib/zstd/lib/compress sys/dev/efidev sys/dev/ipmi sys/sys

Conrad Meyer cem at FreeBSD.org
Sat Dec 15 05:46:06 UTC 2018


Author: cem
Date: Sat Dec 15 05:46:04 2018
New Revision: 342108
URL: https://svnweb.freebsd.org/changeset/base/342108

Log:
  efirt: When present, attempt to use EFI runtime services to shutdown
  
  PR:		maybe related to 233998 (inconclusive at this time)
  Submitted by:	byuu <byuu AT tutanota.com> (previous version)
  Reviewed by:	imp
  Differential Revision:	https://reviews.freebsd.org/D18506

Modified:
  head/share/man/man9/efirt.9
  head/sys/contrib/zstd/lib/compress/zstd_compress_internal.h
  head/sys/contrib/zstd/lib/compress/zstd_opt.c
  head/sys/dev/efidev/efirt.c
  head/sys/dev/ipmi/ipmi.c
  head/sys/sys/efi.h

Modified: head/share/man/man9/efirt.9
==============================================================================
--- head/share/man/man9/efirt.9	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/share/man/man9/efirt.9	Sat Dec 15 05:46:04 2018	(r342108)
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 12, 2018
+.Dd December 11, 2018
 .Dt EFIRT 9
 .Os
 .Sh NAME
@@ -54,7 +54,7 @@
 .Ft int
 .Fn efi_get_time_capabilities "struct efi_tmcap *tmcap"
 .Ft int
-.Fn efi_reset_system "void"
+.Fn efi_reset_system "enum efi_reset type"
 .Ft int
 .Fn efi_set_time "struct efi_tm *tm"
 .Ft int
@@ -123,7 +123,20 @@ if the time could not be retrieved due to a hardware e
 .Pp
 The
 .Fn efi_reset_system
-function requests a warm reset and reboot of the system.
+function requests a reset of the system.
+The
+.Fa type
+argument may be one of the
+.Vt enum efi_reset
+values:
+.Bl -tag -width ".Dv EFI_RESET_SHUTDOWN"
+.It Dv EFI_RESET_COLD
+Perform a cold reset of the system, and reboot.
+.It Dv EFI_RESET_WARM
+Perform a warm reset of the system, and reboot.
+.It Dv EFI_RESET_SHUTDOWN
+Power off the system.
+.El
 .Pp
 The
 .Fn efi_set_time
@@ -239,7 +252,7 @@ The variable could not be saved due to a hardware erro
 .It Dv EROFS
 The variable in question is read-only or may not be deleted.
 .It Dv EDOOFUS
-The varialbe could not be set due to an authentication failure.
+The variable could not be set due to an authentication failure.
 .It Dv ENOENT
 The variable trying to be updated or deleted was not found.
 .El

Modified: head/sys/contrib/zstd/lib/compress/zstd_compress_internal.h
==============================================================================
--- head/sys/contrib/zstd/lib/compress/zstd_compress_internal.h	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/sys/contrib/zstd/lib/compress/zstd_compress_internal.h	Sat Dec 15 05:46:04 2018	(r342108)
@@ -691,6 +691,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* windo
 
 /* debug functions */
 
+#if 0
 MEM_STATIC double ZSTD_fWeight(U32 rawStat)
 {
     U32 const fp_accuracy = 8;
@@ -714,6 +715,7 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 
                 u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );
     }
 }
+#endif
 
 #if defined (__cplusplus)
 }

Modified: head/sys/contrib/zstd/lib/compress/zstd_opt.c
==============================================================================
--- head/sys/contrib/zstd/lib/compress/zstd_opt.c	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/sys/contrib/zstd/lib/compress/zstd_opt.c	Sat Dec 15 05:46:04 2018	(r342108)
@@ -53,10 +53,12 @@ MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)
 }
 
 /* debugging function, @return price in bytes */
+#if 0
 MEM_STATIC double ZSTD_fCost(U32 price)
 {
     return (double)price / (BITCOST_MULTIPLIER*8);
 }
+#endif
 
 static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
 {
@@ -852,8 +854,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
                     for ( ; pos <= end ; pos++ ) {
                         U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
                         U32 const sequencePrice = literalsPrice + matchPrice;
+#if 0
                         DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
                                     pos, ZSTD_fCost(sequencePrice));
+#endif
                         opt[pos].mlen = pos;
                         opt[pos].off = offset;
                         opt[pos].litlen = litlen;
@@ -879,18 +883,22 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
                                 - ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel);
                 assert(price < 1000000000); /* overflow check */
                 if (price <= opt[cur].price) {
+#if 0
                     DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)",
                                 inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen,
                                 opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]);
+#endif
                     opt[cur].mlen = 0;
                     opt[cur].off = 0;
                     opt[cur].litlen = litlen;
                     opt[cur].price = price;
                     memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep));
                 } else {
+#if 0
                     DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)",
                                 inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price),
                                 opt[cur].rep[0], opt[cur].rep[1], opt[cur].rep[2]);
+#endif
                 }
             }
 
@@ -947,8 +955,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
                         int const price = basePrice + ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
 
                         if ((pos > last_pos) || (price < opt[pos].price)) {
+#if 0
                             DEBUGLOG(7, "rPos:%u (ml=%2u) => new better price (%.2f<%.2f)",
                                         pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
+#endif
                             while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; }   /* fill empty positions */
                             opt[pos].mlen = mlen;
                             opt[pos].off = offset;
@@ -957,8 +967,10 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
                             ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory));
                             memcpy(opt[pos].rep, &repHistory, sizeof(repHistory));
                         } else {
+#if 0
                             DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)",
                                         pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));
+#endif
                             if (optLevel==0) break;  /* early update abort; gets ~+10% speed for about -0.01 ratio loss */
                         }
             }   }   }

Modified: head/sys/dev/efidev/efirt.c
==============================================================================
--- head/sys/dev/efidev/efirt.c	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/sys/dev/efidev/efirt.c	Sat Dec 15 05:46:04 2018	(r342108)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/efi.h>
+#include <sys/eventhandler.h>
 #include <sys/kernel.h>
 #include <sys/linker.h>
 #include <sys/lock.h>
@@ -41,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/clock.h>
 #include <sys/proc.h>
+#include <sys/reboot.h>
 #include <sys/rwlock.h>
 #include <sys/sched.h>
 #include <sys/sysctl.h>
@@ -57,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_map.h>
 
 static struct efi_systbl *efi_systbl;
+static eventhandler_tag efi_shutdown_tag;
 /*
  * The following pointers point to tables in the EFI runtime service data pages.
  * Care should be taken to make sure that we've properly entered the EFI runtime
@@ -106,6 +109,10 @@ efi_status_to_errno(efi_status status)
 }
 
 static struct mtx efi_lock;
+static SYSCTL_NODE(_hw, OID_AUTO, efi, CTLFLAG_RWTUN, NULL, "EFI");
+static bool efi_poweroff = true;
+SYSCTL_BOOL(_hw_efi, OID_AUTO, poweroff, CTLFLAG_RWTUN, &efi_poweroff, 0,
+    "If true, use EFI runtime services to power off in preference to ACPI");
 
 static bool
 efi_is_in_map(struct efi_md *map, int ndesc, int descsz, vm_offset_t addr)
@@ -126,6 +133,19 @@ efi_is_in_map(struct efi_md *map, int ndesc, int descs
 	return (false);
 }
 
+static void
+efi_shutdown_final(void *dummy __unused, int howto)
+{
+
+	/*
+	 * On some systems, ACPI S5 is missing or does not function properly.
+	 * When present, shutdown via EFI Runtime Services instead, unless
+	 * disabled.
+	 */
+	if ((howto & RB_POWEROFF) != 0 && efi_poweroff)
+		(void)efi_reset_system(EFI_RESET_SHUTDOWN);
+}
+
 static int
 efi_init(void)
 {
@@ -214,6 +234,12 @@ efi_init(void)
 	}
 #endif
 
+	/*
+	 * We use SHUTDOWN_PRI_LAST - 1 to trigger after IPMI, but before ACPI.
+	 */
+	efi_shutdown_tag = EVENTHANDLER_REGISTER(shutdown_final,
+	    efi_shutdown_final, NULL, SHUTDOWN_PRI_LAST - 1);
+
 	return (0);
 }
 
@@ -224,6 +250,8 @@ efi_uninit(void)
 	/* Most likely disabled by tunable */
 	if (efi_runtime == NULL)
 		return;
+	if (efi_shutdown_tag != NULL)
+		EVENTHANDLER_DEREGISTER(shutdown_final, efi_shutdown_tag);
 	efi_destroy_1t1_map();
 
 	efi_systbl = NULL;
@@ -411,16 +439,24 @@ efi_get_time_capabilities(struct efi_tmcap *tmcap)
 }
 
 int
-efi_reset_system(void)
+efi_reset_system(enum efi_reset type)
 {
 	struct efirt_callinfo ec;
 
+	switch (type) {
+	case EFI_RESET_COLD:
+	case EFI_RESET_WARM:
+	case EFI_RESET_SHUTDOWN:
+		break;
+	default:
+		return (EINVAL);
+	}
 	if (efi_runtime == NULL)
 		return (ENXIO);
 	bzero(&ec, sizeof(ec));
 	ec.ec_name = "rt_reset";
 	ec.ec_argcnt = 4;
-	ec.ec_arg1 = (uintptr_t)EFI_RESET_WARM;
+	ec.ec_arg1 = (uintptr_t)type;
 	ec.ec_arg2 = (uintptr_t)0;
 	ec.ec_arg3 = (uintptr_t)0;
 	ec.ec_arg4 = (uintptr_t)NULL;

Modified: head/sys/dev/ipmi/ipmi.c
==============================================================================
--- head/sys/dev/ipmi/ipmi.c	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/sys/dev/ipmi/ipmi.c	Sat Dec 15 05:46:04 2018	(r342108)
@@ -938,14 +938,14 @@ ipmi_startup(void *arg)
 	} else if (!on)
 		(void)ipmi_set_watchdog(sc, 0);
 	/*
-	 * Power cycle the system off using IPMI. We use last - 1 since we don't
+	 * Power cycle the system off using IPMI. We use last - 2 since we don't
 	 * handle all the other kinds of reboots. We'll let others handle them.
 	 * We only try to do this if the BMC supports the Chassis device.
 	 */
 	if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) {
 		device_printf(dev, "Establishing power cycle handler\n");
 		sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final,
-		    ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 1);
+		    ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 2);
 	}
 }
 

Modified: head/sys/sys/efi.h
==============================================================================
--- head/sys/sys/efi.h	Sat Dec 15 04:53:02 2018	(r342107)
+++ head/sys/sys/efi.h	Sat Dec 15 05:46:04 2018	(r342108)
@@ -42,8 +42,9 @@
 	{0xeb9d2d32,0x2d88,0x11d3,0x9a,0x16,{0x00,0x90,0x27,0x3f,0xc1,0x4d}}
 
 enum efi_reset {
-	EFI_RESET_COLD,
-	EFI_RESET_WARM
+	EFI_RESET_COLD = 0,
+	EFI_RESET_WARM = 1,
+	EFI_RESET_SHUTDOWN = 2,
 };
 
 typedef uint16_t	efi_char;
@@ -184,7 +185,7 @@ int efi_rt_ok(void);
 int efi_get_table(struct uuid *uuid, void **ptr);
 int efi_get_time(struct efi_tm *tm);
 int efi_get_time_capabilities(struct efi_tmcap *tmcap);
-int efi_reset_system(void);
+int efi_reset_system(enum efi_reset type);
 int efi_set_time(struct efi_tm *tm);
 int efi_var_get(uint16_t *name, struct uuid *vendor, uint32_t *attrib,
     size_t *datasize, void *data);


More information about the svn-src-head mailing list