From owner-freebsd-hackers@freebsd.org Mon Dec 10 19:38:48 2018 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 87E87133143F; Mon, 10 Dec 2018 19:38:48 +0000 (UTC) (envelope-from j@nitrology.com) Received: from nitrology.com (wsip-72-215-204-58.ph.ph.cox.net [72.215.204.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1C9EA6B867; Mon, 10 Dec 2018 19:38:46 +0000 (UTC) (envelope-from j@nitrology.com) Received: by nitrology.com (Postfix, from userid 58) id 4E015B419A; Mon, 10 Dec 2018 12:38:32 -0700 (MST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on nitrology.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from m.nitrology.com (unknown [10.255.255.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: evidence) by nitrology.com (Postfix) with ESMTPSA id 1A7C7B4193; Mon, 10 Dec 2018 12:38:31 -0700 (MST) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Date: Mon, 10 Dec 2018 12:38:31 -0700 From: Jason Wolfe To: byuu@tutanota.com Cc: Conrad Meyer , Freebsd Hackers , owner-freebsd-hackers@freebsd.org Subject: Re: I'd like to submit a kernel patch for a new sysctl to use EFI instead of ACPI for poweroff + reboot In-Reply-To: References: <> Message-ID: <23b3fe208bfb2b6ba5e50f4b88a84ac6@nitrology.com> X-Sender: j@nitrology.com User-Agent: Roundcube Webmail/1.3.7 X-Rspamd-Queue-Id: 1C9EA6B867 X-Spamd-Result: default: False [1.03 / 15.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[4]; R_SPF_ALLOW(-0.20)[+a]; NEURAL_HAM_LONG(-0.30)[-0.301,0]; MIME_GOOD(-0.10)[text/plain]; DMARC_NA(0.00)[nitrology.com]; TO_DN_SOME(0.00)[]; NEURAL_SPAM_MEDIUM(0.58)[0.584,0]; RCVD_COUNT_THREE(0.00)[3]; TO_MATCH_ENVRCPT_SOME(0.00)[]; NEURAL_SPAM_SHORT(0.76)[0.763,0]; MX_GOOD(-0.01)[nitrology.com]; IP_SCORE(0.29)[asn: 22773(1.55), country: US(-0.09)]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; RCVD_TLS_LAST(0.00)[]; ASN(0.00)[asn:22773, ipnet:72.215.192.0/20, country:US]; MID_RHS_MATCH_FROM(0.00)[] X-Rspamd-Server: mx1.freebsd.org X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Dec 2018 19:38:48 -0000 Hey, https://wiki.freebsd.org/Phabricator is a good guide on how to get your patch some visibility and hopefully ushered in. Jason On 2018-12-10 06:05, byuu@tutanota.com wrote: > Thank you, this information helped a lot! > > I am not sure where I should submit my patch to ... I'll post it here > if that's okay. If it needs to go somewhere else, please provide > instructions or if you don't mind ... submit it on my behalf ^^; > > This patch has been created against -CURRENT, and has been tested > successfully on 12.0-RC3. It allows me to power off my ASRock X399M > (mATX) motherboard, and should also work for ASRock X399 (ATX) users > who have reported the same problem of ACPI hanging during shutdown. > Hopefully it will be useful to other users in the future who > experience ACPI shutdown issues as a fallback option. > > I relinquish the entire copyright to the FreeBSD project. It's public > domain, no credit is necessary. > > Some notes: > > As requested, I moved IPMI to PRI-2 instead of PRI-1. I then placed > EFI shutdown at PRI-1. > > In the spirit of DRY, I modified efi_reset_system(void) to > efi_reset_system(int type). I did a grep -rn . search on -CURRENT, and > absolutely nothing ever uses efi_reset_system(void), nor is it exposed > via the /dev/efi ioctl interface. I hope this is okay. > > I named the sysctl tunable "hw.efi.poweroff", after the similarly > named "hw.acpi." set of tunables, and the use of "poweroff" over > "shutdown" in various other tunables. Please feel free to rename the > tunable to anything you like. > > I think it would be nice if we exposed this tunable to the "sysctl" > tool, and allowed modifying it at run-time. I didn't want to > complicate the patch, but if you're okay with that, please add that as > well. However, if you're worried about people mucking with the value > inadvertently, I'm okay if it remains a "secret" /boot/loader.conf > option only. > > Lastly, I added the needed event handler headers, and added the new > EFI_RESET_SHUTDOWN define. > > I tried to respect all formatting conventions of the existing code. > But as with everything else, please feel free to make any changes you > like. > > If I can be of any further assistance on this, please let me know. > Thank you very much! > > diff -ru old/sys/dev/efidev/efirt.c new/sys/dev/efidev/efirt.c > --- old/sys/dev/efidev/efirt.c 2018-12-10 04:32:01.231607000 +0900 > +++ new/sys/dev/efidev/efirt.c 2018-12-10 04:45:29.548147000 +0900 > @@ -46,6 +46,8 @@ > #include > #include > #include > +#include > +#include > > #include > #include > @@ -126,6 +128,24 @@ > return (false); > } > > +static void > +efi_shutdown_final(void *unused, int howto) > +{ > + int efi_poweroff; > + > + /* > + * On some systems, ACPI S5 is missing or does not function properly. > + * Allow shutdown via EFI Runtime Services instead with a sysctl > tunable. > + */ > + if((howto & RB_POWEROFF) != 0) { > + efi_poweroff = 0; > + TUNABLE_INT_FETCH("hw.efi.poweroff", &efi_poweroff); > + if (efi_poweroff == 1) { > + efi_reset_system(EFI_RESET_SHUTDOWN); > + } > + } > +} > + > static int > efi_init(void) > { > @@ -214,6 +234,13 @@ > } > #endif > > + /* > + * We use SHUTDOWN_PRI_LAST - 1 to trigger after IPMI, but before > ACPI. > + * When not enabled via sysctl tunable, this will fall through to > ACPI. > + */ > + EVENTHANDLER_REGISTER(shutdown_final, efi_shutdown_final, NULL, > + SHUTDOWN_PRI_LAST - 1); > + > return (0); > } > > @@ -411,16 +438,20 @@ > } > > int > -efi_reset_system(void) > +efi_reset_system(int type) > { > struct efirt_callinfo ec; > > + if (type != EFI_RESET_COLD > + && type != EFI_RESET_WARM > + && type != EFI_RESET_SHUTDOWN) > + 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; > diff -ru old/sys/dev/ipmi/ipmi.c new/sys/dev/ipmi/ipmi.c > --- old/sys/dev/ipmi/ipmi.c 2018-12-10 04:34:07.535522000 +0900 > +++ new/sys/dev/ipmi/ipmi.c 2018-12-10 04:36:35.757611000 +0900 > @@ -938,14 +938,14 @@ > } 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); > } > } > > diff -ru old/sys/sys/efi.h new/sys/sys/efi.h > --- old/sys/sys/efi.h 2018-12-10 04:32:34.850892000 +0900 > +++ new/sys/sys/efi.h 2018-12-10 04:35:41.011396000 +0900 > @@ -43,7 +43,8 @@ > > enum efi_reset { > EFI_RESET_COLD, > - EFI_RESET_WARM > + EFI_RESET_WARM, > + EFI_RESET_SHUTDOWN > }; > > typedef uint16_t efi_char; > @@ -184,7 +185,7 @@ > 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(int 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); > > Dec 9, 2018, 3:35 AM by cem@freebsd.org: > >> Hi, >> >> I think the way you would do this properly is by adding a >> 'EVENTHANDLER_REGISTER(shutdown_final, efi_shutdown_final, ..., >> SHUTDOWN_PRI_LAST - 1);' in efidev/efirt (or '- 2', see below). >> Because the priority number is *lower* than acpi's >> (SHUTDOWN_PRI_LAST), it will be invoked *before* acpi. If an EFI >> shutdown is inappropriate or the particular howto mode is unsupported >> on that system, it can just do return doing nothing; the ACPI >> acpi_shutdown_final handler will be called next. >> >> You can see numerous examples of such handlers in various ARM devices >> which don't have ACPI (grep for >> 'EVENTHANDLER_REGISTER(shutdown_final'). >> >> One other relevant example on x86 is ipmi shutdown, which like I just >> suggested for efi shutdown, registers itself as SHUTDOWN_PRI_LAST - 1 >> to precede ACPI shutdown. I guess if IPMI is configured, maybe it >> should supersede both EFI and ACPI. So maybe your patch should bump >> the IPMI number to SHUTDOWN_PRI_LAST - 2 and add EFI as - 1. >> >> As hinted above, your efirt_shutdown_final() would take the place of >> acpi_shutdown_final() in your callstack above, called from >> kern_reboot() -> shutdown_final event. >> >> I hope that helps, >> Conrad >> On Sat, Dec 8, 2018 at 9:53 AM <> byuu@tutanota.com >> > > wrote: >> >>> >>> Hello, first time poster here, please go easy on me ^-^; >>> >>> I would like to submit a patch for inclusion to the FreeBSD kernel, >>> but want to first see if there is a chance it will be accepted before >>> writing it or 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 directly after EFI_RESET_WARM.) >>> >>> (These two functions are wrappers to invoke the EFI Runtime Services >>> function 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=0", 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 running on an EFI system), I would like to invoke >>> efi_poweroff_system() instead of >>> AcpiEnterSleepStatePrep(ACPI_STATE_S5) >>> >>> This is well after all services have been halted, all disks have been >>> detached, and all USB devices have been detached. acpi_shutdown_final >>> calls AcpiEnterSleepStatePrep (_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 >>> Threadripper 2950X with an ASRock Taichi X399M motherboard, and when >>> I attempt to shutdown my system from FreeBSD 11.2-RELEASE or >>> 12.0-RC3, the system hangs forever and fails to power down. The call >>> frame for this is as follows: >>> >>> kern_psignal(initproc, SIGUSR2); >>> kern_reboot >>> shutdown_final >>> acpi_shutdown_final >>> AcpiEnterSleepStatePre >>> AcpiEvaluateObject >>> AcpiNsEvaluate >>> AcpiPsExecuteMethod >>> AcpiPsParseAml >>> AcpiPsParseLoop //from this point on, it likely varies per DSDT >>> WalkState->AscendingCallback >>> AcpiDsExecEndOp >>> AcpiGbl_OpTypeDispatch[OpType] >>> AcpiExOpcode_1A_0T_0R >>> AcpiExSystemDoSleep >>> AcpiOsSleep >>> 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 acpidump, 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_DEBUG 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. Nothing 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 motherboard 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, but a sysctl as I'm proposing >>> would be beneficial for this and future platforms while users wait >>> for a fix. >>> >>> If someone with kernel commit access would be interested, I can write >>> all of the code against -CURRENT, and submit a diff patch for review. >>> It would be 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 bear with me. >>> >>> Personally, for now, I just monkey patched it into acpica.c and >>> confirmed that the concept works. >>> >>> If there's no interest, then I will drop the matter. >>> >>> Thank you everyone for your time! >>> >>> _______________________________________________ >>> freebsd-hackers@freebsd.org >> >>> mailing list >>> https://lists.freebsd.org/mailman/listinfo/freebsd-hackers >>> >>> To unsubscribe, send any mail to ">> >>> freebsd-hackers-unsubscribe@freebsd.org >>> >> " >>> > > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to > "freebsd-hackers-unsubscribe@freebsd.org"