1

システムのエラー検出および訂正機能をテストするために、データを任意の物理メモリ アドレスに書き込みたいと考えています。既存のカーネル モジュール内の 1 つのコード セグメントは、次のように記述されます。

 u32 addr;
 struct page *page;
 void *mem;

 pci_read_config_dword(priv->mc, I5100_MEMEINJADDRMAT, &addr);

 /* Inject error by writing to address */
 page = pfn_to_page(addr >> PAGE_SHIFT);
 mem = kmap(page) + (addr & (~PAGE_MASK));
 *((volatile u32*) (mem)) = 0x01010101;
 kunmap(page);

I5100_MEMEINJADDRMATi5100 メモリ コントローラ内のレジスタのレジスタ アドレスです。基本的に、メモリアドレスはそのレジスタで取得されます。ページの取得から始まり、ビットごとの操作を実行する残りのコードがわかりません。

私が理解している限り、pfn_to_page引数としてページ フレーム番号を渡すことにより、特定の物理アドレスを含むページを取得するために使用されます。そのaddr >> PAGE_SHIFT部分は、特定のアドレスから対応するページ フレーム番号に変換することです。PAGE_SHIFTでも、正しい使い方がわからない?で使用する正しいデータ型は何PAGE_SHIFTですか?

kmap()適切な仮想ページ アドレスを返し、オフセットを追加して、仮想メモリ アドレスへの正しいポインタを取得します。実際には何をし(addr & (~PAGE_MASK))ますか?

私の仕事は、エラー注入を物理アドレスに書き込むことですか? しかし、上記のコードは仮想アドレスに書き込むようです。他に方法はありますか?

4

2 に答える 2

4

これ:

(addr & (~PAGE_MASK))

addrで設定されているのビットをクリアしますPAGE_MASK。ページ サイズが 4 KB であると仮定すると、 2 12 = 4096PAGE_MASKであるため、12 の最下位ビットが設定される可能性があります。

そうPAGE_MASKです0x00000fff。すると、ビット単位の逆数~PAGE_MASKは単純な0xfffff000ので、addrをこれとビット単位論理積すると、 の下位 12 ビットaddrがクリアされます。

于 2012-12-20T10:43:46.950 に答える
1
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT  12
#define PAGE_SIZE   (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK   (~(PAGE_SIZE-1))

これらの定義は linux-source-3.2.0 で見つけました。しかし、PAGE_MASKは0xfffff000です

したがって、この演算子は最上位 20 ビットをクリアするか、下位 12 ビットの値を取得しようとしていると思います。

于 2014-01-20T08:09:47.113 に答える