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(R) 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!
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 Intel(R)tő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
S4
BIOS állapot a
BIOS segítségével a
lemezre menti a rendszert, az
S4
OS á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
,
S4
OS, és
S5
állapotokat. Ha az
s4bios
értéke egy
(1
), akkor az
S4
BIOS
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 - A DDB elérése a soros
vonalról) 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(R) é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(R) 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(R) é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(R)
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):
<questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése, kérjük erre a címre írjon:
<gabor@FreeBSD.org>.