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_MEMEINJADDRMAT是 i5100 内存控制器中寄存器的寄存器地址。基本上,在该寄存器中检索内存地址。我不明白剩下的代码,从检索页面开始,然后执行按位运算。

据我了解,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,PAGE_MASK则可能会设置其 12 个最低有效位,因为 2 12 = 4096。

所以,PAGE_MASK0x00000fff。然后,按位求逆~PAGE_MASK是简单0xfffff000的,所以当addr按位与:ed 时, 的最低 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 是 0xffffff000

所以我认为这个运算符是清除最高 20 位,或者尝试获取低 12 位的值。

于 2014-01-20T08:09:47.113 回答