12.17. FreeBSD ACPI gebruiken en debuggen

Geschreven door Nate Lawson. Met medewerking van Peter Schultz. Tom Rhodes.

ACPI is een totaal nieuwe manier om apparaten te ontdekken, om energieverbruik te beheren en om een gestandaardiseerde toegang te bieden tot allerlei apparaten die eerder via het BIOS beheerd werden. Er wordt voortdurend vooruitgang geboekt om ACPI op alle systemen te laten werken, maar bugs in de ACPIMachine Language (AML) bytecode van sommige moederborden, onvolledigheden in de subsystemen van de kernel van FreeBSD en bugs in de Intel® ACPI-CA interpreter blijven opduiken.

Deze tekst is bedoeld om u te helpen met het bijstaan van de FreeBSD ACPI beheerders met het vinden van de hoofdoorzaken van problemen die u opmerkt en met het debuggen en het vinden van een oplossing.

12.17.1. Debuginformatie aanleveren

Opmerking: Voordat een probleem wordt gemeld, moet het zeker zijn dat de laatste BIOS versie draait en indien beschikbaar de geïntregeerde controller firmware versie.

Diegenen die meteen een probleem willen indienen, sturen de volgende informatie naar freebsd-acpi@FreeBSD.org:

De meeste FreeBSD-programmeurs lezen de FreeBSD-CURRENT mailinglijst, maar problemen gaan bij voorkeur ook naar freebsd-acpi zodat ze zeker gezien worden. Het kan enige tijd duren voordat er antwoord komt, omdat deze mensen elders ook nog volledige banen hebben. Als de bug niet meteen duidelijk is, komt er waarschijnlijk en verzoek om een PR in te dienen via send-pr(1). Als er een PR moet worden opgesteld, dan dient alle hierboven gevraagde informatie vermeld te worden. Dit helpt om het probleem te kunnen volgen en oplossen. Het sturen van een PR zonder eerst freebsd-acpi te mailen is niet wenselijk, aangezien men PRs gebruikt als herinnering van bestaande problemen, niet als rapportagesysteem. Mogelijk is een probleem al eens door iemand anders gemeld.

12.17.2. Achtergrond

ACPI is aanwezig op alle moderne computers die voldoen aan de ia32 (x86), ia64 (Itanium) of amd64 (AMD) architecturen. De volledige standaard heeft vele mogelijkheden zoals CPU-prestatiebeheer, energiebeheer, thermische zones, diverse batterijsystemen, ingebedde controllers en busnummering. De meeste systemen implementeren minder dan de volledige standaard. Een desktopsysteem implementeert bijvoorbeeld meestal alleen busnummering, terwijl laptops mogelijk ook koeling- en batterijbeheer ondersteunen. Laptops hebben ook suspend en resume (slapen en wakker worden) met hun eigen aanverwante comlexiteit.

Een ACPI-compliant systeem heeft verscheidene componenten. Het BIOS- en chipsetverkopers bieden verscheidene vaste tabellen aan zoals FADT in het geheugen die zaken als de APIC-afbeelding (gebruikt voor SMP), configuratieregisters, en eenvoudige configuratiewaarden specificeren. Ook wordt er een tabel van bytecode (de Differentiated System Description Table of DSDT) geleverd die een op een boomstructuur lijkende namespace biedt voor apparaten en methoden.

Het stuurprogramma ACPI moet de voorgedefinieerde tabellen verwerken, een interpreter voor de bytecode implementeren en apparaatstuurprogramma's en de kernel aanpassen om informatie van het ACPI-subsysteem te accepteren. Intel heeft een interpreter beschikbaar gesteld (ACPI-CA) die door FreeBSD en ook door Linux® en NetBSD gebruikt wordt. De ACPI-CA-broncode staat in src/sys/contrib/dev/acpica. De lijmcode die ACPI-CA laat werken met FreeBSD staat in src/sys/dev/acpica/Osd. Stuurprogramma's die verscheidene ACPI-apparaten implementeren staan in src/sys/dev/acpica.

12.17.3. Algemene problemen

Wil ACPI goed werken, dan moeten alle onderdelen goed werken. Hieronder staan enkele algemene problemen in volgorde van hoe vaak ze optreden en enkele mogelijke oplossingen of manieren om de problemen te vermijden.

12.17.3.1. Muisproblemen

Soms doet een muis het niet bij het opstarten uit de slaapstand. Een bekend lapmiddel is het toevoegen van hint.psm.0.flags="0x3000" aan /boot/loader.conf. Als dat niet werkt, dan wordt aangeraden een bugrapport in te sturen, zoals eerder is beschreven.

12.17.3.2. Suspend/resume

ACPI heeft drie slaapstanden waarbij het geheugen (RAM) wordt ingezet. Dit zijn de STR-toestanden S1-S3, en nog een slaap-met-gebruik-van-harde-schijf toestand (STD) die S4 heet. S5 is “zacht uit” en is de normale status van een systeem als het is aangesloten maar niet is aangezet. S4 kan feitelijk op twee manieren geïmplementeerd worden: S4BIOS is een slaapstand naar schijf met behulp van het BIOS en S4OS wordt volledig door het besturingssysteem geïmplenteerd.

als eerste dienen de sysctl hw.acpi items die iets met de slaapstand te maken hebben gecontroleerd te worden. Hieronder staan de resultaten voor een Thinkpad:

hw.acpi.supported_sleep_state: S3 S4 S5
hw.acpi.s4bios: 0

Dit betekent dat hier acpiconf -s gebruikt kan worden om S3, S4OS en S5 te testen. Als s4bios gelijk was aan (1), dan zou er S4BIOS ondersteuning zijn in plaats van S4 OS.

Als suspend/resume getest moet worden, dient, indien ondersteund, bij S1 begonnen te worden. Deze toestand heeft de grootste kans om te werken, omdat deze niet veel stuurprogrammaondersteuning vereist. Niemand heeft nog S2 geïmplementeerd, maar het is ongeveer hetzelfde als S1. Daarna wordt S3 getest. Dit is het diepste STR-niveau en heeft uitgebreide ondersteuning van stuurprogramma's nodig om hardware goed opnieuw te kunnen starten. Mochten er blokkades optreden, dan kan naar de freebsd-acpi lijst gemaild worden. Er kan echter geen snelle oplossing verwacht worden, omdat er nog de nodige stuurprogramma's/hardware liggen om getest en bewerkt te worden.

Een veelvoorkomend probleem met suspend/resume is dat veel apparaatstuurprogramma's hun firmware, registers of apparaatgeheugen niet fatsoenlijk opslaan, herstellen, of herinitialiseren. Een eerste poging om het probleem te vinden omvat:

# sysctl debug.bootverbose=1
# sysctl debug.acpi.suspend_bounce=1
# acpiconf -s 3

Deze test emuleert de suspend/resume-cyclus van alle apparaten zonder daadwerkelijk naar de toestand S3 te gaan. In sommige gevallen kunt u zo eenvoudig problemen vaststellen (bijvoorbeeld het verliezen van de firmware-toestand, timeout van de apparaatwaakhond, en steeds opnieuw iets proberen). Merk op dat het systeem niet werkelijk naar de toestand S3 gaat, wat inhoudt dat apparaten geen spanning verliezen waardoor velen prima zullen werken zelfs als de suspend/resume-methoden geheel ontbreken, dit in tegenstelling tot de echte toestand S3.

Moeilijkere gevallen vereisen aanvullende hardware, dat is een serieële poort/kabel voor de serieële console of een Firewire poort/kabel voor dcons(4), en vaardigheden in het debuggen van de kernel.

Om een probleem te kunnen isoleren helpt het om zoveel mogelijk stuurprogramma's uit de kernel te halen. Als dit werkt, kan er teruggewerkt worden naar het stuurprogramma dat schuldig is aan het falen. Meestal vertonen binaire stuurprogramma's als nvidia.ko, X11 beeldschermstuurprogramma's en USB de meeste problemen, terwijl bijvoorbeeld Ethernet-interfaces meestal meteen goed werken. Als de stuurprogramma's zonder problemen geladen en verwijderd kunnen worden, dan is dit te automatiseren door de juiste commando's in /etc/rc.suspend en /etc/rc.resume te zetten. Er staat een voorbeeld (achter commentaartekens) voor het laden en verwijderen van een stuurprogramma. Als het beeldscherm er na wakker worden vreemd uitziet, kan geprobeerd worden hw.acpi.reset_video op nul te zetten. Met langere of kortere waarden voor hw.acpi.sleep_delay kan bekeken worden of dat helpt.

In geval van problemen is het ook een optie om een recente Linux distibutie met ondersteuning voor ACPI support te starten en daarvan de suspend/resume ondersteuning op dezelfde hardware uit te proberen. Als het werkt met Linux, dan is het waarschijnlijk een FreeBSD stuurprogrammaprobleem en als het mogelijk is uit te vinden over welk stuurprogramma het gaat, kan dat bijdragen aan het oplossen van het probleem. ACPI houdt zich in het algemeen niet bezig met andere stuurprogramma's zoals geluid, ATA, enzovoort. Als er dus een echt probleem met een stuurprogramma is, dan is waarchijnlijk uiteindelijk ook nodig naar de freebsd-current lijst te posten en naar de beheerder van het stuurprogramma. Voor degenen met moed is het vooral aan te raden een paar printf(3)s in problematische stukken van een stuurprogramma te plaatsen voor debugging om na te gaan waar de resumefunctie precies hangt.

Tot slot kan geprobeerd worden om ACPI uit te zetten en in plaats daarvan APM aan te zetten. Als suspend/resume werkt met APM, is het wellicht verstandig het daarbij te houden, vooral met wat oudere apparatuur (voor 2000). Producenten hebben nogal wat tijd nodig gehad om ACPI ondersteuning goed te krijgen en voor oudere hardware is het waarschijnlijker dat er BIOS-problemen zijn met ACPI.

12.17.3.3. Systeem hangt (tijdelijk of permanent)

Meestal is het hangen van het systeem het gevolg van verloren interrupts of een interruptstorm. Chipsets kunnen een heleboel problemen hebben, afhankelijk van hoe het BIOS interrupts instelt voor het opstarten, of de APIC (MADT) tabel correct is en de routering van het System Control Interrupt (SCI).

Interruptstorms kunnen onderscheiden worden van verloren geraakte interrupts door de uitvoer van vmstat -i te controleren en de regel met acpi0 goed te lezen. Als de teller in toenemende mate hoger staat dan enkele per seconde, dan is sprake van een interruptstorm. Als het systeem lijkt te hangen, is het wellicht nog mogelijk door te dringen tot de DDB (CTRL+ALT+ESC) en show interrupts uit te voeren.

De beste hoop in geval van interruptproblemen is om APIC-ondersteuning uit te zetten met hint.apic.0.disabled="1" in loader.conf.

12.17.3.4. Panics

Panics zijn relatief zeldzaam met ACPI en krijgen de hoogste prioriteit bij het oplossen. Eerst moeten de verschillende gebeurtenissen waarmee de panic (als mogelijk) te reproduceren is geïsoleerd worden en moet een backtrace gemaakt worden. options DDB dient aangezet te worden en er dient een seriële console (Paragraaf 27.6.5.3) of een dump(8) partitie te komen. In DDB is een backtrace te maken met tr. Als de backtrace handmatig opgeschreven moet worden, is het belangrijk dat in ieder geval de bovenste en onderste vijf (5) regels van de backtrace genoteerd worden.

Daarna dient getracht te worden het systeem te starten zonder ACPI. Als dat werkt, is het ACPI-subsysteem geïsoleerd en kunnen de verschillende debug.acpi.disable-waarden uitgeprobeerd worden. In acpi(4) staan enkele voorbeelden.

12.17.3.5. Systeem slaat aan na slaapstand of stop

hw.acpi.disable_on_poweroff="0" kan uitgezet worden in loader.conf(5). Hierdoor schakelt ACPI bepaalde gebeurtenissen tijdens het afsluitproces niet uit. Om dezelfde redenen moeten sommige systemen deze waarde altijd op 1 (standaard) hebben staan. In het algemeen lost dit een probleem op waarbij een systeem spontaan weer opkomt nadat het in slaapstand is gezet of geheel gestopt is.

12.17.3.6. Overige problemen

Als er nog andere problemen zijn met ACPI (met een docking station of apparaten niet gedetecteerd, enzovoort), dan kan een mail met beschijving naar de mailinglijst gezonden worden. Sommige zaken kunnen echter gerelateerd zijn aan delen van het ACPI-subsysteem die nog niet af zijn, dus het kan in sommige gevallen een tijd duren. Gebruikers moeten soms geduld en de bereidheid om eventuele patches uit te proberen hebben.

12.17.4. ASL, acpidump en IASL

Het grootste probleem is dat BIOS-producenten vaak incorrecte (of gewoon foutieve) bytecode leveren. Dit blijkt doorgaans uit kernelboodschappen als:

ACPI-1287: *** Error: Method execution failed [\\_SB_.PCI0.LPC0.FIGD._STA] \\
(Node 0xc3f6d160), AE_NOT_FOUND

Vaak kunnen dergelijke problemen geoplost worden door de BIOS bij te werken tot de laatste revisie. De meeste consoleberichten zijn onschuldig, maar als er andere problemen zijn, zoals batterijstatus die niet werkt, dan ligt het voor de hand te zoeken naar problemen in de AML-code. De bytecode die AML genoemd wordt, wordt gecompileerd van een broncodetaal ASL. Deze staat weer in een tabel DSDT. Met acpidump(8) kan een kopie van de ASL gemaakt worden. Dan moeten zowel de opties -t (laat inhoud van vaste tabellen zien) als -d (disassembleer AML naar ASL) gebruikt worden. In Debuginformatie aanleveren staat een voorbeeld.

De eenvoudigste eerste controle is de ASL-code opnieuw compileren en kijken of er foutmeldingen optreden. Waarschuwingen kunnen doorgaans genegeerd worden, maar fouten zijn bugs die er meestal toe leiden dat ACPI niet correct werkt. Om ASL te hercompileren:

# iasl eigen.asl

12.17.5. ASL repareren

Op langere termijn is het de bedoeling dat voor vrijwel elke machine ACPI werkt zonder enig ingrijpen van de gebruiker. Op dit moment wordt er echter nog gewerkt aan oplossingen voor veel voorkomende vergissingen die BIOS-producenten maken. De Microsoft® interpreter (acpi.sys en acpiec.sys) controleert niet strikt of het BIOS volledig aan de standaard voldoet, waardoor het voorkomt dat BIOS-makers die alleen testen onder Windows® bepaalde fouten in hun ASL nooit correct repareren. FreeBSD hoopt door te gaan met de identificatie en documentatie van welk niet-standaard gedrag precies wordt toegelaten door Microsoft's interpreter en te dit te repliceren zodat FreeBSD kan werken zonder dat gebruikers zich gedwongen zien om de ASL te repareren. Als een tijdelijke oplossing en om te helpen met het in kaart brengen van bepaald gedrag, kan de ASL handmatig gerepareerd worden. Mocht dit lukken, dan wordt erop aangedrongen een diff(1) van de oude en de nieuwe ASL te mailen, zodat het foutieve gedrag mogelijk in ACPI-CA kan worden verwerkt, waardoor andere gebruikers niet meer handmatig met hun ASL aan de gang hoeven.

Hieronder staat een lijst algemene foutmeldingen, hun oorzaken en hoe ze op te lossen:

12.17.5.1. _OS afhankelijkheden

Sommige AMLs gaan ervan uit dat de wereld enkel bestaat uit Windows versies. FreeBSD kan zich voordoen als elk OS om te kijken of dit problemen oplost. Een gemakkelijke manier om dit te doen is hw.acpi.osname="Windows 2001" in te stellen in /boot/loader.conf of andere gelijksoortige strings die in een ASL staan.

12.17.5.2. Ontbrekende return-opdrachten

Sommige methoden hebben geen specifieke returnwaarde, zoals wel vereist wordt door de standaard. Hoewel ACPI-CA hier niets mee doet, heeft FreeBSD de mogelijkheid tot impliciete returns. Er kunnen ook expliciete return-opdrachten toegevoegd worden waar vereist, als het bekend is welke waarden teruggevoerd moeten worden. Om iasl te dwingen tot compilatie van ASL kan de schakeloptie -f gebruikt worden.

12.17.5.3. De standaard AML aanpassen

Nadat eigen.asl aangepast is, kan deze als volgt gecompileerd worden:

# iasl eigen.asl

Met de optie -f is af te dwingen dat de AML gemaakt wordt, zelfs als er compileerfouten optreden. Sommige fouten (zoals ontbrekende return-opdrachten) worden automatisch opgelost door de interpreter.

DSDT.aml is de standaardnaam voor het bestand dat door iasl wordt geproduceerd. Dit is in plaats van de foutieve versie uit het BIOS (die nog steeds aanwezig is in het flashgeneugen) te laden door /boot/loader.conf als volgt te wijzigen:

acpi_dsdt_load="YES"
acpi_dsdt_name="/boot/DSDT.aml"

DSDT.aml moet in de map /boot staan.

12.17.6. Debuguitvoer van ACPI verkrijgen

Het stuurprogramma ACPI heeft een zeer flexibele debugfaciliteit. Er kan zowel een verzameling van subsystemen aangegeven worden als het niveau van uitvoerigheid. De te debuggen subsystemen worden aangegeven als lagen (“layers”) en zijn opgedeeld in ACPI-CA-componenten (ACPI_ALL_COMPONENTS) en ACPI-hardware-ondersteuning (ACPI_ALL_DRIVERS). De uitvoerigheid van debuguitvoer wordt aangegeven als het niveau (“level”) en gaat van CPI_LV_ERROR (alleen fouten rapporteren) tot ACPI_LV_VERBOSE (alles). Het niveau is een bitmasker en dus kunnen er meerdere opties tegelijk ingeschakeld worden (gescheiden door spaties). In de praktijk wordt wellicht een seriële console gebruikt om de uitvoer te loggen als deze zo omvangrijk is dat de console berichtbuffer vol loopt (misschien wel meerdere keren). Een complete lijst van de individuele lagen en niveaus staat in acpi(4).

Debuguitvoer staat standaard niet aan. Door options ACPI_DEBUG toe te voegen aan het bestand met kernelinstellingen als ACPI als de kernel is gebouwd, wordt het ingeschakeld. Door ACPI_DEBUG=1 toe te voegen aan /etc/make.conf wordt het systeembreed ingeschakeld. Als ACPI als module wordt gebruikt (de normale situatie), dan hoeft slechts de module acpi.ko opnieuw gecompileerd te worden:

# cd /sys/modules/acpi/acpi
&& make clean &&
make ACPI_DEBUG=1

acpi.ko moet in /boot/kernel komen te staan en de gewenste debuglaag en het gewenste niveau van uitvoerigheid dienen toegevoegd te worden aan loader.conf. Hieronder een voorbeeld waarmee debuguitvoer wordt aangezet voor alle ACPI-CA-componenten en alle ACPI-hardware-stuurprogramma's (CPU, LID, enzovoort. Het niveau van uitvoerigheid is het laagst mogelijke. Er worden alleen fouten gemeld.

debug.acpi.layer="ACPI_ALL_COMPONENTS ACPI_ALL_DRIVERS"
debug.acpi.level="ACPI_LV_ERROR"

Als de gezochte informatie wordt veroorzaakt door een specifieke gebeurtenis (bijvoorbeeld in en uit slaapstand gaan), dan kunnen wijzigingen aan loader.conf achterwege blijven en in plaats daarvan kan sysctl gebruikt worden om laag en niveau in te stellen na het opstarten en zo het systeem voor te bereiden op die specifieke gebeurtenis. De sysctls hebben dezelfde namen als de parameters in loader.conf.

12.17.7. Verwijzingen

Meer informatie over ACPI staat op de volgende locaties: