这种将数据写入特定物理内存地址的方式如何工作?

时间:2012-12-20 10:39:07

标签: linux memory kernel

我想将数据写入任意物理内存地址,以测试我系统的错误检测和纠正功能。现有内核模块中的一个代码段如下所示:

 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))实际上做了什么?

我的任务是将错误注入写入物理地址?但上面的代码似乎写入了一个虚拟地址。还有其他办法吗?

2 个答案:

答案 0 :(得分:3)

此:

(addr & (~PAGE_MASK))

将清除addr中设置的PAGE_MASK中的位。假设页面大小为4 KB,PAGE_MASK可能会设置其12个最低有效位,因为2 12 = 4096。

所以,PAGE_MASK0x00000fff。然后,逐位反~PAGE_MASK只是0xfffff000,所以当addr按位 - 并且:ed时,addr的最低12位被清除。< / p>

答案 1 :(得分: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位的值。