Az ACPI az eszközök felderítésének, energiagazdálkodásának és a korábban a BIOS által kezelt hardverek szabványosított hozzáférésének alapjaiban új módja. Az ACPI folyamatosan fejlődik, de útját az egyes alaplapok ACPI Machine Language (AML) bytekód implementációjában megjelenő hibák, a FreeBSD rendszermag alrendszereinek befejezetlensége és az Intel® ACPI-CA értelmezőjében levő hibák lassítják.
Ez a leírás azzal a szándékkal készült, hogy segítsünk a felhasználóknak megtalálni az általuk tapasztalt problémák gyökerét és ezzel segíteni az ACPI fejlesztőket a nyomonkövetésében és kijavításában. A fejlesztők köszönik, hogy ezt elolvassuk és segédkezünk a rendszerünkkel kapcsolatban felmerülő problémák orvosolásában!
Megjegyzés: Mielőtt beküldenénk bármilyen problémát is, gondoskodjunk róla, hogy a BIOS-unk, és ha lehetséges, akkor a beágyazott vezérlők, legfrissebb verzióját használjuk.
Megkérnénk azokat, akik hibát akarnak bejelenteni, hogy a következő információkat küldjék a freebsd-acpi@FreeBSD.org címre:
A hibás működés leírása, beleértve a rendszer típusát és gyártmányát, illetve minden olyat, aminek köze lehet a hibához. Ha eddig még nem tapasztaltuk, igyekezzünk minél pontosabban leírni a hiba keletkezésének folyamatát.
A boot -v paranccsal indított rendszer dmesg(8) kimenetét, beleértve a vizsgálni kívánt hiba által okozott összes hibaüzenetet.
A boot -v paranccsal és az ACPI használata nélkül indított rendszer dmesg(8) kimenete abban az esetben, ha ez segít megoldani a problémát.
A sysctl hw.acpi parancs kimenete. Ezzel egyébként kitűnően kideríthető, milyen lehetőségeket is kínál fel a rendszerünk.
Az általunk használt ACPI forrásnyelvének (ACPI Source Language, ASL) elérhetősége az interneten. Mivel ezek akár igen nagyok is lehetnek, ezért a listára közvetlenül ne küldjünk ASL kódokat! Az ASL másolatát az alábbi parancs kiadásával hozhatjuk létre:
# acpidump -dt > név-rendszer.asl
(Adjuk meg a név helyett a bejelentkezéshez használt nevünket, a rendszer helyett pedig a gyártót/típust. Például: njl-FooCo6000.asl)
Habár a legtöbb fejlesztő a FreeBSD-CURRENT levelezési listat figyeli, a problémáink leírását mindenképpen a freebsd-acpi listára küldjük, hogy biztosan észrevegyék. A fejlesztők azt kérik, hogy legyünk türelmesek, hiszen emellett mindannyian teljes állásban is dolgoznak. Ha az általunk felfedezett hiba nem teljesen egyértelmű, akkor a fejlesztők valószínűleg meg fognak kérni arra, hogy a send-pr(1) használatával hozzunk róla létre egy hivatalos hibajelentést. A hibajelentés készítésekor lehetőleg a fentebb megadott információkat ugyanúgy adjuk meg. Ez segít a probléma szemmel tartásában és elhárításában. Az freebsd-acpi lista kihagyása nélkül közvetlenül ne küldjünk hibajelentést, mivel a hibabejelentő rendszert elsősorban emlékeztetőnek használjuk, nem pedig a hibák tényleges bejelentésére. Gyakran előfordul, hogy valaki korábban már találkozott az adott problémával.
Az ACPI minden olyan modern számítógépben megtalálható, mely megfelel az ia32 (x86), ia64 (Itanium) vagy amd64 (AMD) architektúrának. A teljes szabvány rengeteg lehetőséget biztosít, többek közt a processzor teljesítményének kezelését, az energiaszintek vezérlését, hőzónákat, különféle akkumulátor rendszereket, beágyazott vezérlők és a buszok felsorolását. A legtöbb rendszer általában nem a teljes szabványt valósítja meg. Például egy asztali rendszer általában csak a buszok felsorolásával kapcsolatos részeket tartalmazza, miközben egy laptop felajánlhatja a hűtés és az akkumulátor kezelését is. A laptopokban gyakorta találunk készenléti üzemmódot a maguk elbonyolított formájában.
Egy ACPI-nak megfelelő rendszert számos összetevő alkot. A BIOS-ok és chipkészletek gyártói a memóriában egy előre rögzített ponton elhelyeznek bizonyos táblázatokat (például FADT), amelyekkel megadják például az APIC összerendeléseit (ezt az SMP rendszerek használják), a konfigurációs regisztereket és az egyszerűbb konfigurációs értékeket. Itt ezenkívül még bytekódok egy táblázata (amit Differenciált rendszerleírtó táblának, Differentiated System Description Table, DSDT nevezünk) is megtalálható, ahol az eszközök és módszerek nevei szerepelnek faszerű elrendezésben.
Az ACPI-hoz tartozó meghajtónak képesnek kell lennie értelmezni ezeket a rögzített táblázatokat, implementálni egy bytekód-értelmezőt, módosítani az eszközmeghajtókat és a rendszermagot az ACPI alrendszerből érkező információk befogadásához. A Linuxszal és a NetBSD-vel közösen a FreeBSD kapott egy ilyen értelmezőt az Inteltől (ACPI-CA). Az ACPI-CA forráskódja a rendszer forrásai között, a src/sys/dev/acpica könyvtárban található. A src/sys/dev/acpica/0sd könyvtárban található források pedig lehetővé teszik, hogy az ACPI-CA működhessen FreeBSD-n. Végezetül, az ACPI eszközöket megvalósító meghajtók a src/sys/dev/acpica könyvtárban találhatóak.
Az ACPI megfelelő működéséhez minden alkotórésznek helyesen kell működnie. A most következendőkben előfordulásuk gyakorisága szerint felsorolunk néhány ismert problémát, valamint a hozzájuk tartozó javításokat vagy elkerülésük módszerét.
Egyes esetekben felfüggesztett állapotból visszatérve az egerünk nem hajlandó működni. Ezt úgy lehet elkerülni, ha /boot/loader.conf állományba beírjuk a hint.psm.0.flags="0x3000" sort. Ha ez nem segít, akkor a fentieknek megfelelően küldjünk be egy hibajelentést.
Az ACPI három (STR) állapotban képes a fizikai memória segítségével készenléti módba váltani, ezek az S1-S3, és egy állapotban használja a lemezt (STD), amelyet S4-nek hívnak. Az S5 neve a “szoftveres kikapcsolás”, ami egy olyan állapotot takar, amikor a rendszerünk áram alatt van, de még nem üzemel. Az S4BIOS állapot a BIOS segítségével a lemezre menti a rendszert, az S4OS állapotot pedig teljes egészében az operációs rendszer valósítja meg.
A rendszerünk által ismert készenléti módokat a sysctl hw.acpi paranccsal ellenőrizhetjük. Íme mindez egy Thinkpad esetén:
hw.acpi.supported_sleep_state: S3 S4 S5 hw.acpi.s4bios: 0
Ez azt jelenti, hogy az acpiconf -s
parancs kiadásával kipróbálhatjuk
az S3,
S4OS, és
S5 állapotokat. Ha az
s4bios
értéke egy
(1), akkor az
S4BIOS
támogatása helyett az S4
OS állapotot kapjuk.
A felfüggesztés és folytatás kipróbálása során kezdjük az S1 állapottal, már amennyiben az támogatott a rendszerünkön. Ez az állapot többnyire használható, mivel nem igényel túlságosan sok támogatást a meghajtó részéről. Eddig még senki sem implementálta az S2 állapotot, de ha ezt is tudja a rendszerünk, akkor az S1-hez hasonlót nyerünk vele. A következő próba az S3 állapoté. Ez a legmélyebb STR állapot, és a hardver megfelelő újraélesztéséhez rengeteg támogatás szükségeltetik a meghajtó részéről. Ha gondjaink lennének a rendszerünk felébresztésével, nyugodtan írjunk egy levelet a freebsd-acpi listára, ám a probléma gyors megoldódásában ne reménykedjünk, hiszen ehhez még temérdek meghajtón és hardveren kell tesztelni és kell dolgozni.
Felfüggesztés és folytatás esetén gyakori probléma, hogy sok eszközmeghajtó nem menti el, nem állítja vissza vagy éppen nem hozza újra rendesen működésbe az adott eszközön található firmware-t, a regisztereket vagy memóriát. Az okok felderítéséhez először érdemes a következőket kipróbálni:
# sysctl debug.bootverbose=1 # sysctl debug.acpi.suspend_bounce=1 # acpiconf -s 3
Ezzel a módszerrel tesztelni tudjuk az összes meghajtó felfüggesztési és folytatási rutinjait anélkül, hogy ténylegesen S3 állapotba helyeznénk az eszközt. Bizonyos esetekben ezzel könnyen elcsíphető a hiba (például a firmware állapotának elvesztése, watchdog time out, megállás nélküli újrapróbálkozások). A rendszer ilyenkor nem vált S3 állapotra, vagyis az eszköz nem kerül energiatakarékos állapotba, és eltérően a valós S3 állapottól továbbra is működik még abban az esetben is, amikor a szükséges felfüggesztési és folytatási rutinok teljesen hiányoznak.
Komolyabb esetben további segédeszközökre lesz szükségünk, vagyis soros portra és kábelre a soros vonali nyomkövetéshez, vagy Firewire portra és kábelre a dcons(4) használatához, valamint némi tapasztalatra a rendszermagon belüli hibakeresésben.
A problémát nagy mértékben
segíti különválasztani, ha
igyekszünk minél több meghajtót
kivenni a rendszermagból. Ha így javul a
helyzet, akkor már könnyen le lehet
szűkíteni arra a meghajtóra a kört,
aminek betöltésével esetleg gondok
akadhatnak. Általában ilyenek a bináris
meghajtók, mint például az
nvidia.ko, az X11
megjelenítésért felelős és az
USB eszközök meghajtói,
miközben az Ethernet eszközök remekül
szoktak működni. Ha különösebb gond
nélkül képesek vagyunk betölteni
és eltávolítani ezeket a
meghajtókat, akkor ezt a folyamatot
önállósítani is tudjuk úgy,
hogy az /etc/rc.suspend és
/etc/rc.resume szkriptekbe
beillesztjük az ehhez szükséges parancsokat.
Ezekben egyébként találunk is egy
megjegyzésbe rakott példát a
meghajtók betöltéséről
és eltávolításáról.
Ha az ébresztés után elszemetelődik
a képernyő tartalma, akkor állítsuk
át a hw.acpi.reset_video
változó értékét
nullára (0). Sokat segíthet
meg az is, ha a hw.acpi.sleep_delay
értékét csökkentjük vagy
növeljük.
Megpróbálhatjuk azt is, hogy elindítunk egy frissebb Linux disztribúciót ACPI támogatással és ugyanazon a hardveren kipróbáljuk az általa felkínált felfüggesztési és folytatási lehetőséget. Ha Linux alatt ez megbízhatóan működik, akkor nagy a valószínűsége, hogy ez FreeBSD alatt az egyik meghajtó hibájából fakadóan nem használható. Így fokozatosan le is tudjuk szűkíteni, hogy pontosan melyikkel lehet a gond, és ezzel a fejlesztők munkáját segítjük. Megjegyeznénk, hogy az ACPI-t karbantartó fejlesztők általában nem foglalkoznak más meghajtókkal (például hangkártya vagy ATA stb.), ezért az adott meghajtóval kapcsolatos hibáról javasolt értesíteni a freebsd-current listát és a meghajtóért felelős fejlesztőt is. Ha van egy kis kedvünk és időnk, mi magunk is belebiggyeszthetünk a meghajtóba néhány printf(3) függvényt annak kiderítésére, pontosan hol is fagy le a folytatási funkció.
Végül megpróbálkozhatunk az ACPI kikapcsolásával is, és áttérhetünk helyette az APM használatára. Ha az APM-mel működnek a készenléti állapotok, akkor érdemes inkább azzal dolgozni, különösen a régebbi (2000 előtti) hardverek esetében. A gyártóknak eltartott egy ideig, amíg rendes ACPI támogatást voltak képesek adni, ezért a régebbi hardvereknél inkább a BIOS-nak akadnak gondjai az ACPI-val.
A legtöbb rendszer olyankor akad meg, amikor sok megszakítás elveszik, vagy amikor éppen sok megszakítás érkezik egyszerre. A chipkészleteknek számos baja származik abból, hogy a BIOS milyen módon állítja be a rendszer indítása előtt a megszakításokat, mennyire helyes az APIC (MADT) táblázata és hogyan vezérli a Rendszervezérlő megszakítást (System Control Interrupt, SCI).
A megszakítás-viharok a vmstat -i parancs kimenetében szereplő elveszett megszakításokból azonosíthatók be, ahol keressünk rá az acpi0 sorra. Ha ez a számláló másodpercenként kettőnél többel növekszik, akkor a megszakításaink viharba keveredtek. Ha a rendszer látszólag lefagyott, próbáljuk meg előhívni a DDB-t (konzolban a CTRL+ALT+ESC) és gépeljük be, hogy show interrupts.
A megszakítási problémákkal kapcsolatban egyetlen reményünk az APIC támogatás kikapcsolása lehet a loader.conf állományban a hint.apic.0.disabled="1" sor hozzáadásával.
Az ACPI-vel kapcsolatos végzetes hibák viszonylag ritkák, és javításuk a legfontosabb. Ilyenkor az első teendőnk elkülöníteni a hiba reprodukálásának egyes lépéseit és (ha lehetséges) lekérni a hívási láncot. Kövessük az options DDB és a soros vonali konzol beállításához adott tanácsokat (lásd 26.6.5.3 Szakasz) vagy hozzunk létre egy dump(8) partíciót. A DDB-ben a hívási láncot a tr parancs segítségével kérhetjük le. Ha kézzel írjuk le láncot, akkor legalább az alsó öt (5) és a felső öt (5) sorát mindenképpen jegyezzük fel!
Ezután próbáljuk meg úgy
szűkíteni a probléma
lehetőségét, hogy az
ACPI használata nélkül
indítjuk a rendszert. Ha ezzel nincs semmi gond, akkor
a debug.acpi.disable
változó
értékének megfelelő
beállításával egyenként meg
tudjuk figyelni az ACPI alrendszer egyes
részeit. Ehhez példákat az acpi(4)
man oldalon találunk.
Először is próbáljuk meg a hw.acpi.disable_on_poweroff változó értékét 0-ra állítani a loader.conf(5) állományban. Ezzel távoltartjuk az ACPI alrendszert a rendszer leállítási folyamatától. Egyes rendszereknek valamilyen okból kifolyólag szükségük van itt az 1 (az alapértelmezett) értékre. Ez többnyire megoldja a problémát, amikor a rendszer váratlanul elindul a készenléti mód aktiválásákor vagy kikapcsoláskor.
Ha más gondjaink lennének az ACPI-val (dokkoló állomásunk van, egyes eszközöket nem vesz észre stb.), akkor természetesen erről is küldjünk egy leírást a levelezési listára. Azonban vegyük figyelembe, hogy egyes problémák a ACPI alrendszer eddig még nem implementált, befejezetlen részeihez kötődnek, ezért azok megoldása még várat magára. Kérünk mindenkit, hogy legyen türelemmel és álljon készen a kiküldött javítások tesztelésére!
A problémák leggyakoribb forrása, hogy a BIOS-gyártók rossz (vagy kifejezetten hibás!) bytekódokat adnak. Ez általában a következőhöz hasonló rendszerüzenetből derül ki:
ACPI-1287: *** Error: Method execution failed [\\_SB_.PCI0.LPC0.FIGD._STA] \\ (Node 0xc3f6d160), AE_NOT_FOUND
Az ilyen jellegű hibákat gyakran úgy
lehet orvosolni, ha a BIOS-unkat
frissítjük a legújabb verzióra. A
legtöbb ilyen üzenet teljesen ártalmatlan, de
ha vannak más problémáink is,
például az akkumulátor állapota nem
olvasható le, akkor először az
AML környékén
érdemes kutakodnunk. A bytekód, más
néven AML, az ASL
elnevezésű forrásnyelvből
származik. Az AML egy
DSDT néven ismert
táblázatban található meg. Az
ASL másolatát az
acpidump(8) paranccsal készíthetjük el.
Paraméterként egyaránt adjuk meg a
-t
(megmutatja a rögzített
táblák tartalmát) és
-d
(visszafejti az AML
kódokat az ASL nyelvére)
kapcsolókat. A felírás pontos
formátumát a A
nyomkövetési információk
beküldése című szakaszban
olvashatjuk.
Elsőként próbáljuk meg újrafordítani az így nyert ASL programot és keressünk benne hibákat. A figyelmeztetések általában nyugodtan figyelmen kívül hagyhatóak, azonban a hibák olyan implementációs hibákra utalnak, amelyek akadályozzák az ACPI helyes működését. Az ASL újrafordítását az alábbi paranccsal tudjuk elvégezni:
# iasl saját.asl
Végeredményben az a célunk, hogy az ACPI megfelelő működéséhez senkinek se kelljen hozzányúlnia semmihez. Azonban még mindig szükség van BIOS-gyártók által elkövetett gyakori hibák elkerülésének kifejlesztésére. A Microsoft® értelmezője (acpi.sys és acpiec.sys) nem ellenőrzi szigorúan a szabvány szerinti megfelelést, ezért számos olyan BIOS-gyártó, akik csak Windows® alatt tesztelik az ACPI implementációjukat, soha nem fogják kijavítani a ASL kódjukban ejtett hibáikat. Reménykedünk, hogy folyamatosan sikerül felderíteni és dokumentálni a Microsoft értelmezője által eltűrt szabványon kívüli viselkedést és leutánozni FreeBSD alatt is, hogy így ne kelljen a felhasználóknak kézzel a saját ASL forrásaikat javítgatni. Az ebből fakadó hibákat úgy tudjuk elkerülni és segíteni a fejlesztőknek azonosítani a hozzá társuló viselkedést, hogy magunk javítjuk az ASL-ben felfedezett hibákat. Ha ez beválik, akkor küldjük el a régi és új ASL közti diff(1)-et a fejlesztőknek, akik így majd az ACPI-CA-ban ki tudnak dolgozni egy megoldást a hibás viselkedésre, ezzel a javításunk szükségtelenné válik.
Most pedig következzenek a legismertebb hibaüzenetek, az okaik és javításuk:
Néhány AML úgy gondolja, hogy a világ csak a különböző Windows verziókból áll. A FreeBSD-nek megadható, hogy másik operációs rendszernek adja ki magát, és ezzel talán meg is szüntethető pár hiba. Ezt a legegyszerűbb úgy tudjuk megtenni, ha a /boot/loader.conf állományhoz hozzáfűzzük a hw.acpi.osname="Windows 2001" sort, vagy itt egy olyan karakterláncot adunk meg, amit az ASL forrásban láttunk.
Bizonyos módszerek a szabvány szerint
elvártaktól eltérően nem adnak
vissza explicit módon értéket. Mivel az
ACPI-CA ezt nem kezeli le, ezért a
FreeBSD részéről tartalmaz egy olyan
módosítást, amivel implicit módon
is vissza lehet adni értéket. Ha biztosak
akarunk lenni a visszaadni kívánt
értékben, akkor helyezzünk el a
megfelelő helyekre explicit Return
utasításokat. Az iasl a
-f
paraméterrel
kényszeríthető az ilyen
ASL források
lefordítására.
Miután módosítottuk a saját.asl állományunkat, így tudjuk lefordítani:
# iasl saját.asl
Az -f
kapcsoló
megadásával
kikényszeríthetjük az
AML létrehozását
még abban az esetben is, amikor hibákat
tartalmaz. Ügyeljünk rá, hogy bizonyos
hibákat (például a hiányzó
visszatérési értékeket) a
fordító magától
kikerül.
Az iasl alapértelmezett kimenete a DSDT.aml állomány. A /boot/loader.conf átírásával így tudjuk ezzel helyettesíteni a BIOS-unk hibás változatát (ami még mindig megtalálható a flash memóriában):
acpi_dsdt_load="YES" acpi_dsdt_name="/boot/DSDT.aml"
Ehhez ne felejtsük el a saját DSDT.aml állományunkat bemásolni a /boot könyvtárba.
Az ACPI meghajtója nagyon rugalmas nyomkövetési lehetőségekkel rendelkezik. Ennek révén ugyanúgy megadhatjuk a nyomonkövetni kívánt alrendszert, mint ahogy annak mélységét is. A nyomkövetni kívánt alrendszereket “rétegekként” adjuk meg, valamint ezek ACPI-CA komponensekre (ACPI_ALL_COMPONENTS) és ACPI hardvertámogatásra (ACPI_ALL_DRIVERS) bomlanak le. A nyomkövetéskor keletkező kimenet részletességét a “szintként” adjuk meg, ami az ACPI_LV_ERROR-tól (csak a hibák) ACPI_LV_VERBOSE-ig (minden) terjedhet. A “szint” itt egy bitmaszk, ezért szóközzel elválasztva egyszerre több beállítás megadható. Ha túlságosan sok üzenet érkezik a konzol üzenetpufferébe, akkor szükségünk lehet a soros konzol keresztüli nyomkövetésre is. Az összes szint és réteg az acpi(4) man oldalon található meg.
A nyomkövetés alapértelmezés szerint nem engedélyezett. Az engedélyezéséhez hozzá kell adnunk az options ACPI_DEBUG sort a rendszermagunk beállításait tartalmazó állományhoz, amennyiben a rendszermagba fordítjuk az ACPI támogatást. Ha az /etc/make.conf állományba írjuk bele az ACPI_DEBUG=1 sort, akkor azt globálisan engedélyezhetjük. Ha modulként használjuk, elegendő csak a következő módon újrafordítani az acpi.ko modult:
# cd /sys/modules/acpi/acpi && make clean && make ACPI_DEBUG=1
Telepítsük fel a acpi.ko modult a /boot/kernel könyvtárba és állítsuk be a számunkra megfelelő szintet és réteget a loader.conf állományban. Az alábbi példában engedélyezzük az összes ACPI-CA komponens és az összes ACPI hardvermeghajtó (processzor, LID stb.) nyomkövetését. Csak a hibaüzeneteket írja ki részletesen.
debug.acpi.layer="ACPI_ALL_COMPONENTS ACPI_ALL_DRIVERS" debug.acpi.level="ACPI_LV_ERROR"
Ha az általunk keresett információt egy adott esemény váltja ki (például egy felfüggesztés vagy egy ébresztés), akkor nem is fontos átírnunk hozzá a loader.conf állományt, hanem helyette a rendszer indítása után használjuk a sysctl parancsot a réteg és a szint megadására akkor, amikor a rendszert felkészítjük az eseményre. A sysctl változókat ugyanúgy nevezték el, mint a loader.conf állományban található beállításokat.
Az ACPI-ről az alábbi helyeken találunk részletesebb információkat:
Az ACPI levelezési lista archívuma: http://lists.freebsd.org/pipermail/freebsd-acpi/
A korábbi ACPI levelezési lista archívuma: http://home.jp.FreeBSD.org/mail-list/acpi-jp/
Az ACPI 2.0 specifikációja: http://acpi.info/spec.htm
A FreeBSD következő man oldalai: acpi(4), acpi_thermal(4), acpidump(8), iasl(8), acpidb(8)
A DSDT nyomkövetése (angolul). (Példának a Compaqot hozza fel, de általánosságban véve hasznos.)
Ha kérdése van a FreeBSD-vel kapcsolatban, a következő
címre írhat (angolul): <freebsd-questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése,
kérjük erre a címre írjon: <gabor@FreeBSD.org>.