如何解决在内核模块中分配物理上连续的页面
我正在尝试使用 alloc_pages_exact 函数在 DRAM 中分配物理上连续的页面。当我尝试分配 10MB 的页面时,返回的地址始终为 0。但是当我尝试分配 1MB 的页面时,分配几乎是立即的。另外,有人可以告诉我如何找到DRAM的确切行大小吗?我不得不搜索我的 RAM 的数据表才能弄清楚。我想知道是否有一个命令可以确定 DRAM 的行大小。早些时候我认为系统页面大小也应该是 DRAM 行大小,但结果系统页面大小是 4kB,而我计算出的行大小变成了 8kB。请帮忙。 代码:
static int __init hello_entry(void){
unsigned long i = 0;
unsigned long j = 0;
unsigned long counter;
int fault = 0;
char default_value = 0xff;
unsigned long size_of_memory_to_test_bytes = 10 * 1024 * 1024;//10MB chunk
unsigned long page_size = 8 * 1024;//8kB page size. From data sheet for elpida 4GB ddr3 ram
unsigned long number_of_pages = size_of_memory_to_test_bytes / page_size;
unsigned long number_of_hammer_access = 200000;
printk("Number Of Bytes to allocate: %ld\n",number_of_pages * page_size);
char* pages = (char *)alloc_pages_exact(number_of_pages * page_size,GFP_KERNEL);
while(pages == 0);//The Program must wait till enough pages have been allocated!
printk("Starting Address: %x",pages);
char *hammerRow0,*hammerRow1,*victimRow;
char hammerRow0_data,victimRow_data,hammerRow1_data,read_midvalue;
printk(KERN_ALERT "Memory Test Entry!\n");
printk(KERN_ALERT "Page Size: %ld\n",page_size);
printk(KERN_ALERT "Cache Line Size: %d\n",cache_line_size());
//The design consists of two hammer rows which will be repeatedly accessed one after another
//There will be a victim row in between the two hammer rows,kind of like a victim row sandwiched between two hammer rows
//This will server two purposes:
//1. Greater probability of inducing bitflip in the victim row due to repeated access of two adjacent rows.
//2. Clearing out the row buffer of DRAM chip so that it is guaranteed that the wordline will be accessed to access the data
printk(KERN_INFO "Rowhammer Test Starts\n");
for(counter = 0; counter < number_of_pages - 2; counter++){
//Doing the rowhammer test on every page of dram
hammerRow0 = pages + counter;
victimRow = hammerRow0 + page_size;
hammerRow1 = victimRow + page_size;
//Storing initial data into rows to check them later for errors
for(i = 0; i < page_size / sizeof(char); i++){
//Setting all bits of dram 1 to maximize the possibility of charge leak
hammerRow0[i] = default_value;
victimRow[i] = default_value;
hammerRow1[i] = default_value;
}
//Starting Hammer Test
//printk(KERN_INFO "Rowhammer Test Starts\n");
fault = 0;
for(j = 0; j < number_of_hammer_access; j++){
//hammerRow0 access
//This is an x86 specific funnction that executes CLFLUSH. Mre info on CLFLUSh: https://c9x.me/x86/html/file_module_x86_id_30.html
clflush_cache_range(hammerRow0,sizeof(char));
read_midvalue = hammerRow0[0]; //Reading the first value present in the page
//hammerRow1 access
clflush_cache_range(hammerRow1,sizeof(int));
read_midvalue = hammerRow1[0]; //Reading the first value present in the page
}
//Checking the victim row for errors
for(i = 0; i < page_size / sizeof(int); i++){
victimRow_data = victimRow[i];
if(victimRow_data != default_value){
printk(KERN_ALERT "victimRow Fault (After Hammering) at index %d: Present Value: %x \t Expected Value: %x:\tRow numer %d\n",i,0xff,counter);
fault = 1;
}
}
if(fault == 1){
printk(KERN_ALERT "Rowhammer Test Failed\n");
return 0;
}
else {
//printk(KERN_ALERT "Rowhammer Test Passed for Row %d\n",counter);
}
}
printk(KERN_ALERT "Rowhammer Test Passed\n");
return 0;
}
static void __exit hello_exit(void){
printk(KERN_INFO "Memory Test Exit!\n");
}
module_init(hello_entry);
module_exit(hello_exit);
//Licensing Info
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jonvonton");
MODULE_DESCRIPTION("Rowhammer Testing");
解决方法
alloc_pages
和 family 支持的最大页面大小为 2 的 MAX_ORDER
次方。 MAX_ORDER
通常为 11,除非被 CONFIG_FORCE_MAX_ZONEORDER
内核配置覆盖(仅针对某些架构设置,并且可以手动配置)。
MAX_ORDER
值为 11 允许分配 2048 个页面,对于最常用的页面大小 4096,允许最大分配大小为 8388608 (8 MiB)。
我不知道如何确定 DRAM 行大小,但它可能与系统页面大小无关,因为后者由架构的 MMU 决定(大多数架构为 4096)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。