Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Dec 2018 18:52:01 +0100 (CET)
From:      <byuu@tutanota.com>
To:        <freebsd-hackers@freebsd.org>
Subject:   I'd like to submit a kernel patch for a new sysctl to use EFI instead of ACPI for poweroff + reboot
Message-ID:  <LTDwcvo--3-1@tutanota.com>

next in thread | raw e-mail | index | archive | help
Hello, first time poster here, please go easy on me ^-^;

I would like to submit a patch for inclusion to the FreeBSD kernel, but wan=
t to first see if there is a chance it will be accepted before writing it o=
r not.

Currently, /usr/src/sys/dev/efidev/efirt.c contains the efi_reset_system() =
function, which calls EFI_RESET_WARM. It's exposed in /usr/src/sys/sys/efi.=
h

I would like to add efi_poweroff_system() to efirt.c, which is identical to=
 efi_reset_system(), but with EFI_RESET_SHUTDOWN as arg1, which we have to =
add as an enum item to efi.h as well (its value is 2, so it would go direct=
ly after EFI_RESET_WARM.)

(These two functions are wrappers to invoke the EFI Runtime Services functi=
on ResetSystem with EfiResetWarm and EfiResetShutdown. FreeBSD's loader.eli=
 uses them to implement its reboot and poweroff commands, for example.)

Next, I would like to add a patch to /usr/src/sys/dev/acpica/acpi.c to acpi=
_shutdown_final to check a new kernel sysctl, not picky about the name, but=
 something like "hw.acpi.efi_shutdown=3D0", which can be optionally changed=
 to 1 by the users. It could be changed at run-time with no ill effect.

When this option is set to 1, and efi_systbl_phys is not NULL (eg we are ru=
nning on an EFI system), I would like to invoke efi_poweroff_system() inste=
ad of AcpiEnterSleepStatePrep(ACPI_STATE_S5)

This is well after all services have been halted, all disks have been detac=
hed, and all USB devices have been detached. acpi_shutdown_final calls Acpi=
EnterSleepStatePrep (_PTS), followed by AcpiEnterSleepState (_S5), and that=
's it. The idea is to reuse all of the shutdown handling we can.

If it would be desired, I could do the same for reset events to invoke efi_=
reset_system().

...

The reason I am requesting this, is because I am the owner of a Threadrippe=
r 2950X with an ASRock Taichi X399M motherboard, and when I attempt to shut=
down my system from FreeBSD 11.2-RELEASE or 12.0-RC3, the system hangs fore=
ver and fails to power down. The call frame for this is as follows:

kern_psignal(initproc, SIGUSR2);
=C2=A0 kern_reboot
=C2=A0 =C2=A0 shutdown_final
=C2=A0 =C2=A0 =C2=A0 acpi_shutdown_final
=C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiEnterSleepStatePre
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiEvaluateObject
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiNsEvaluate
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiPsExecuteMethod
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiPsParseAml
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiPsParseL=
oop=C2=A0 //from this point on, it likely varies per DSDT
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 WalkS=
tate->AscendingCallback
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 AcpiDsExecEndOp
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 AcpiGbl_OpTypeDispatch[OpType]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 AcpiExOpcode_1A_0T_0R
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 AcpiExSystemDoSleep
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AcpiOsSleep
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pause("acpislp", 300) (eg tsleep)

I do not know why, but the call to pause never returns. I have tried over a=
 dozen things to find a fix for this: analyzing my DSDT ASL code via acpidu=
mp, disabling SMT + all cores, wrapping pause in a critical section, trying=
 SLEEP instead of pause, trying a spinloop instead of pause, trying to skip=
 the AcpiEnterSleepStatePrep call, building a kernel with options ACPI_DEBU=
G and trying to selectively disable every device driver and ACPI subsystem =
possible (including USB) while still allowing me to get to a login prompt, =
tweaking every sysctl I could find around ACPI, USB, debugging, etc. Nothin=
g helped.

Looking into Linux' ACPI support, they have acpi_no_s5, which they claim is=
 used for certain motherboards which lack an _S5 DSDT entry.

I believe my proposed patch would be useful both for the case of a missing =
_S5 entry, as well as for when there are bugs in FreeBSD, or the motherboar=
d DSDT, or in Intel's ASL parser, or in the hardware itself. Obviously, it'=
s most desirable to fix ACPI on the Threadripper + Taichi X399 platform, bu=
t a sysctl as I'm proposing would be beneficial for this and future platfor=
ms while users wait for a fix.

If someone with kernel commit access would be interested, I can write all o=
f the code against -CURRENT, and submit a diff patch for review. It would b=
e only a small amount of code, maybe 30 lines or so, with appropriate error=
 checking and fallbacks in place. Again, I'm very new to this, so please be=
ar with me.

Personally, for now, I just monkey patched it into acpica.c and confirmed t=
hat the concept works.

If there's no interest, then I will drop the matter.

Thank you everyone for your time!




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