The branch main has been updated by royger:

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

commit db16856110cbdbdfdc3c8d44edae1b3a7463198e
Author:     Roger Pau Monné <[email protected]>
AuthorDate: 2026-02-24 20:23:08 +0000
Commit:     Roger Pau Monné <[email protected]>
CommitDate: 2026-02-27 07:39:11 +0000

    xen/acpi: implement hook to notify Xen about entering sleep state
    
    This is required so that ACPI power-off (entering S5) works as expected, as
    the ACPI PM1a and PM1b blocks might not be accessible by dom0 directly.
    Additionally, Xen also needs to do cleanup before entering a sleep state,
    so it needs to be notified about it.
    
    With this patch FreeBSD dom0 now powers off the host correctly:
    
    acpi0: Powering system off...
    (XEN) [   85.686598] arch/x86/hvm/emulate.c:415:d0v0 fixup p2m mapping for 
page fedc6 added
    (XEN) [   85.687606] arch/x86/hvm/emulate.c:415:d0v0 fixup p2m mapping for 
page fbc10 added
    (XEN) [   85.692357] Preparing system for ACPI S5 state.
    (XEN) [   85.692702] Disabling non-boot CPUs ...
    (XEN) [   85.694471] Broke affinity for IRQ9, new: {0-7}
    [...]
    (XEN) [   85.903118] Entering ACPI S5 state.
    
    Should be a non-functional change when not running as a Xen dom0.
    
    Reviewed by: kib
    Sponsored by: Citrix Systems R&D
    MFC after: 2 weeks
    Differential revision: https://reviews.freebsd.org/D55504
---
 sys/conf/files                   |  1 +
 sys/dev/acpica/Osd/OsdHardware.c | 13 +++++++
 sys/dev/acpica/acpivar.h         | 13 +++++++
 sys/dev/xen/acpi/xen-acpi.c      | 75 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+)

diff --git a/sys/conf/files b/sys/conf/files
index 4913efebf00d..632fddef2cb5 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3578,6 +3578,7 @@ dev/xdma/xdma_mbuf.c              optional xdma
 dev/xdma/xdma_queue.c          optional xdma
 dev/xdma/xdma_sg.c             optional xdma
 dev/xdma/xdma_sglist.c         optional xdma
+dev/xen/acpi/xen-acpi.c                optional xenhvm
 dev/xen/balloon/balloon.c      optional xenhvm
 dev/xen/blkfront/blkfront.c    optional xenhvm
 dev/xen/blkback/blkback.c      optional xenhvm
diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c
index fbaf76d2a91a..4252cbc63222 100644
--- a/sys/dev/acpica/Osd/OsdHardware.c
+++ b/sys/dev/acpica/Osd/OsdHardware.c
@@ -37,6 +37,8 @@
 
 extern int     acpi_susp_bounce;
 
+int (*acpi_prepare_sleep)(uint8_t state, uint32_t a, uint32_t b, bool ext);
+
 ACPI_STATUS
 AcpiOsEnterSleep(UINT8 SleepState, UINT32 RegaValue, UINT32 RegbValue)
 {
@@ -45,6 +47,17 @@ AcpiOsEnterSleep(UINT8 SleepState, UINT32 RegaValue, UINT32 
RegbValue)
        if (acpi_susp_bounce)
                return (AE_CTRL_TERMINATE);
 
+       if (acpi_prepare_sleep != NULL)
+       {
+               int ret = acpi_prepare_sleep(SleepState, RegaValue, RegbValue,
+                   ACPI_REDUCED_HARDWARE ? true : AcpiGbl_ReducedHardware);
+
+               if (ret < 0)
+                       return (AE_ERROR);
+               if (ret > 0)
+                       return (AE_CTRL_TERMINATE);
+       }
+
        return (AE_OK);
 }
 
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index aa8d5bd0971f..b86c6c1aa3c6 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -610,6 +610,19 @@ int                acpi_pxm_parse(device_t dev);
 int            acpi_map_pxm_to_vm_domainid(int pxm);
 bus_get_cpus_t         acpi_get_cpus;
 
+/*
+ * Hook for ACPI sleep routine.
+ */
+extern int (*acpi_prepare_sleep)(uint8_t state, uint32_t a, uint32_t b,
+    bool ext);
+
+static inline void
+acpi_set_prepare_sleep(
+    int (*hook)(uint8_t state, uint32_t a, uint32_t b, bool ext))
+{
+       acpi_prepare_sleep = hook;
+}
+
 #ifdef __aarch64__
 /*
  * ARM specific ACPI interfaces, relating to IORT table.
diff --git a/sys/dev/xen/acpi/xen-acpi.c b/sys/dev/xen/acpi/xen-acpi.c
new file mode 100644
index 000000000000..1e46883e2c86
--- /dev/null
+++ b/sys/dev/xen/acpi/xen-acpi.c
@@ -0,0 +1,75 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Citrix Systems R&D
+ * All rights reserved.
+ *
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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>
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+
+#include <machine/_inttypes.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+
+#include <dev/acpica/acpivar.h>
+
+#include <xen/xen-os.h>
+
+static int prepare_sleep_state(uint8_t state, uint32_t a, uint32_t b, bool ext)
+{
+       struct xen_platform_op op = {
+               .cmd = XENPF_enter_acpi_sleep,
+               .interface_version = XENPF_INTERFACE_VERSION,
+               .u.enter_acpi_sleep.val_a = a,
+               .u.enter_acpi_sleep.val_b = b,
+               .u.enter_acpi_sleep.sleep_state = state,
+               .u.enter_acpi_sleep.flags =
+                   ext ? XENPF_ACPI_SLEEP_EXTENDED : 0,
+       };
+       int error;
+
+       error = HYPERVISOR_platform_op(&op);
+       if (error)
+               printf("Xen notify ACPI sleep failed - "
+                   "State %#x A %#x B %#x: %d\n", state, a, b, error);
+
+       return (error ? error : 1);
+}
+
+static int init_xen_acpi_sleep(void *arg)
+{
+       if (!xen_initial_domain())
+               return (0);
+
+       acpi_set_prepare_sleep(&prepare_sleep_state);
+       return (0);
+}
+
+SYSINIT(xen_sleep, SI_SUB_CONFIGURE, SI_ORDER_ANY, init_xen_acpi_sleep, NULL);

Reply via email to