2013-09-30 11 views

Odpowiedz

35

Dużo odlewów po prostu "działa dobrze". Jednak nie jest to bardzo surowe. Nic nie stoi na przeszkodzie, aby rzucić kod u32 na adres u32 * i usunąć go, ale nie jest to zgodne z interfejsem API jądra i jest podatne na błędy.

__iomem to plik cookie używany przez Sparse, narzędzie służące do wyszukiwania ewentualnych błędów kodowania w jądrze. Jeśli nie skompilujesz swojego kodu jądra przy włączonej funkcji Sparse, __iomem i tak zostanie zignorowane.

Użyj Sparse, najpierw instalując go, a następnie dodając C=1 do swojego wywołania make. Na przykład, gdy buidling modułu za pomocą:

make -C $KPATH M=$PWD C=1 modules 

__iomem jest zdefiniowany w następujący sposób:

# define __iomem  __attribute__((noderef, address_space(2))) 

Dodawanie (i wymagające) ciastko jak __iomem dla wszystkich I/O dostęp jest sposób być bardziej rygorystyczny i unikać błędów programowania. Nie chcesz odczytywać/zapisywać z/do regionów pamięci I/O z adresami bezwzględnymi, ponieważ zazwyczaj używasz pamięci wirtualnej. Zatem

void __iomem *ioremap(phys_addr_t offset, unsigned long size); 

nazywa się zwykle uzyskać wirtualny adres I/O adresu fizycznego offset, na określonej długości size w bajtach. ioremap() zwraca wskaźnik z krytym __iomem ciasteczka, więc może teraz być używane z funkcjami inline jak readl()/writel() (choć jest to teraz zaleca się stosowanie bardziej wyraźne makr ioread32()/iowrite32(), na przykład), które akceptują __iomem adresy.

Ponadto, atrybut Sparse używa atrybutu noderef, aby upewnić się, że nie zinterpretowano wskaźnika __iomem. Dereferencje powinny działać w niektórych architekturach, w których wejścia/wyjścia są rzeczywiście mapowane na pamięć, ale inne architektury używają specjalnych instrukcji dostępu do operacji we/wy iw tym przypadku dereferencje nie będą działać. wygląd

Miejmy na przykład:

void *io = ioremap(42, 4); 

Rzadki nie jest zadowolony:

warning: incorrect type in initializer (different address spaces) 
    expected void *io 
    got void [noderef] <asn:2>* 

Lub:

u32 __iomem* io = ioremap(42, 4); 
pr_info("%x\n", *io); 

Rzadki nie jest zadowolony albo:

warning: dereference of noderef expression 

W ostatnim przykładzie pierwsza linia jest poprawna, ponieważ ioremap() zwraca jej wartość do zmiennej .Ale potem to oceniamy i nie powinniśmy.

To sprawia Sparse szczęśliwa:

void __iomem* io = ioremap(42, 4); 
pr_info("%x\n", ioread32(io)); 

Konkluzja: zawsze używać __iomem gdzie jest to wymagane (jako typ zwracany lub jako typ parametru) i używać Rzadki, aby upewnić się, że tak zrobiliśmy. Ponadto: nie usuwaj zaznaczenia wskaźnika __iomem.

Edit: Oto wielki LWN article temat powstania __iomem i funkcjami, używając go.

Powiązane problemy