Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 06 Feb 2026 14:47:08 +0000
From:      Olivier Certner <olce@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d2aa0a4dace1 - main - acpi: New R/O 'hw.acpi.s4bios_supported' sysctl, gate S4BIOS with it
Message-ID:  <6985feec.3c7bf.535c3c1c@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by olce:

URL: https://cgit.FreeBSD.org/src/commit/?id=d2aa0a4dace1d0cf8d52614c25b6a8f5cf03fd32

commit d2aa0a4dace1d0cf8d52614c25b6a8f5cf03fd32
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-01-09 13:43:23 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-02-06 14:45:22 +0000

    acpi: New R/O 'hw.acpi.s4bios_supported' sysctl, gate S4BIOS with it
    
    This new sysctl knob indicates whether the ACPI implementation supports
    S4BIOS (FACS present with bit S4BIOS_F set, as per the standard).
    
    If S4BIOS is not supported, do not allow 'hw.acpi.s4bios' to be set to
    true.
    
    This is also in preparation of probably switching the default for
    'hw.acpi.s4bios' to false once OSPM-initiated S4 support is ready, in
    which case administrators need some way to determine whether
    firmware-initiated S4 support is possible.  For now, we keep the default
    of setting 'hw.acpi.s4bios' to true (1) when S4BIOS is supported.
    
    Reviewed by:    obiwac
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D54627
---
 sys/amd64/acpica/acpi_wakeup.c |  2 +-
 sys/dev/acpica/acpi.c          | 35 +++++++++++++++++++++++++++++++----
 sys/dev/acpica/acpivar.h       |  8 ++++++++
 sys/i386/acpica/acpi_wakeup.c  |  2 +-
 4 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index 8cada2f4f911..6e6b9ac618dd 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -218,7 +218,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
 		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);
 
 		/* Call ACPICA to enter the desired sleep state */
-		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
+		if (state == ACPI_STATE_S4 && acpi_should_do_s4bios(sc))
 			status = AcpiEnterSleepStateS4bios();
 		else
 			status = AcpiEnterSleepState(state);
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 53099db8ae84..59ae4624f407 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -193,6 +193,7 @@ static void	acpi_system_eventhandler_sleep(void *arg,
 		    enum power_stype stype);
 static void	acpi_system_eventhandler_wakeup(void *arg,
 		    enum power_stype stype);
+static int	acpi_s4bios_sysctl(SYSCTL_HANDLER_ARGS);
 static enum power_stype	acpi_sstate_to_stype(int sstate);
 static int	acpi_sname_to_sstate(const char *sname);
 static const char	*acpi_sstate_to_sname(int sstate);
@@ -624,9 +625,12 @@ acpi_attach(device_t dev)
     if (AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER)
 	sc->acpi_handle_reboot = 1;
 
-    /* Only enable S4BIOS by default if the FACS says it is available. */
+    /*
+     * Mark whether S4BIOS is available according to the FACS, and if it is,
+     * enable it by default.
+     */
     if (AcpiGbl_FACS != NULL && AcpiGbl_FACS->Flags & ACPI_FACS_S4_BIOS_PRESENT)
-	sc->acpi_s4bios = true;
+	sc->acpi_s4bios = sc->acpi_s4bios_supported = true;
 
     /*
      * Probe all supported ACPI sleep states.  Awake (S0) is always supported,
@@ -754,9 +758,13 @@ acpi_attach(device_t dev)
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
 	OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0,
 	"sleep delay in seconds");
-    SYSCTL_ADD_BOOL(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
-	OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0,
+    SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+	OID_AUTO, "s4bios", CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE,
+	sc, 0, acpi_s4bios_sysctl, "CU",
 	"On hibernate, have the firmware save/restore the machine state (S4BIOS).");
+    SYSCTL_ADD_BOOL(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+	OID_AUTO, "s4bios_supported", CTLFLAG_RD, &sc->acpi_s4bios_supported, 0,
+	"Whether firmware supports saving/restoring the machine state (S4BIOS).");
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
 	OID_AUTO, "verbose", CTLFLAG_RW, &sc->acpi_verbose, 0, "verbose mode");
     SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
@@ -4433,6 +4441,25 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
     return (error);
 }
 
+static int
+acpi_s4bios_sysctl(SYSCTL_HANDLER_ARGS)
+{
+    struct acpi_softc *const sc = arg1;
+    bool val;
+    int error;
+
+    val = sc->acpi_s4bios;
+    error = sysctl_handle_bool(oidp, &val, 0, req);
+    if (error != 0 || req->newptr == NULL)
+	return (error);
+
+    if (val && !sc->acpi_s4bios_supported)
+	return (EOPNOTSUPP);
+    sc->acpi_s4bios = val;
+
+    return (0);
+}
+
 static int
 acpi_sname_to_sstate(const char *sname)
 {
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 51881c580d4b..d585fc8f2e23 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -65,6 +65,7 @@ struct acpi_softc {
 
     int			acpi_standby_sx;
     bool		acpi_s4bios;
+    bool		acpi_s4bios_supported;
 
     int			acpi_sleep_delay;
     int			acpi_do_disable;
@@ -530,6 +531,13 @@ acpi_d_state_to_str(int state)
     return (strs[state]);
 }
 
+static __inline bool
+acpi_should_do_s4bios(struct acpi_softc *sc)
+{
+    MPASS(!sc->acpi_s4bios || sc->acpi_s4bios_supported);
+    return (sc->acpi_s4bios);
+}
+
 char		*acpi_name(ACPI_HANDLE handle);
 int		acpi_avoid(ACPI_HANDLE handle);
 int		acpi_disabled(char *subsys);
diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c
index 96be64de017b..b5390f3cd659 100644
--- a/sys/i386/acpica/acpi_wakeup.c
+++ b/sys/i386/acpica/acpi_wakeup.c
@@ -240,7 +240,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
 		pmap_remap_lowptdi(true);
 
 		/* Call ACPICA to enter the desired sleep state */
-		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
+		if (state == ACPI_STATE_S4 && acpi_should_do_s4bios(sc))
 			status = AcpiEnterSleepStateS4bios();
 		else
 			status = AcpiEnterSleepState(state);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6985feec.3c7bf.535c3c1c>