我想将数据写入任意物理内存地址,以测试我系统的错误检测和纠正功能。现有内核模块中的一个代码段如下所示:
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))
实际上做了什么?
我的任务是将错误注入写入物理地址?但上面的代码似乎写入了一个虚拟地址。还有其他办法吗?
答案 0 :(得分:3)
此:
(addr & (~PAGE_MASK))
将清除addr
中设置的PAGE_MASK
中的位。假设页面大小为4 KB,PAGE_MASK
可能会设置其12个最低有效位,因为2 12 = 4096。
所以,PAGE_MASK
是0x00000fff
。然后,逐位反~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位的值。