简体   繁体   English

在内核模块中分配物理上连续的页面

[英]Allocating physically contiguous pages in Kernel Module

I am trying to allocate physically contiguous pages in DRAM using the alloc_pages_exact function.我正在尝试使用 alloc_pages_exact 函数在 DRAM 中分配物理上连续的页面。 When I try to allocate 10MB of pages, the returned address is always 0. But when I try to allocate 1MB of pages, the allocation is almost immediate.当我尝试分配 10MB 的页面时,返回的地址始终为 0。但是当我尝试分配 1MB 的页面时,分配几乎是立即的。 Also, can someone please tell me how to find the exact row size of DRAM?另外,有人可以告诉我如何找到DRAM的确切行大小吗? I had to search the datasheet of my RAM to figure it out.我不得不搜索我的 RAM 的数据表才能弄清楚。 I was wondering if there is a command to determine the row size of DRAM.我想知道是否有一个命令可以确定 DRAM 的行大小。 Earlier I thought that the System page size should be the DRAM row size as well, but the System page size turned out to be 4kB and my calculated row size came to be 8kB.早些时候我认为系统页面大小也应该是 DRAM 行大小,但结果系统页面大小是 4kB,而我计算出的行大小变成了 8kB。 Please help.请帮忙。 Code:代码:

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, victimRow_data, 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");

The maximum size in pages supported by alloc_pages and family is 2 to the power of MAX_ORDER . alloc_pages和 family 支持的最大页面大小是alloc_pages 2 MAX_ORDER MAX_ORDER is usually 11 unless overridden by the CONFIG_FORCE_MAX_ZONEORDER kernel configuration (which is only set for some architectures, and it may be manually configurable). MAX_ORDER通常为 11,除非被CONFIG_FORCE_MAX_ZONEORDER内核配置覆盖(仅针对某些体系结构设置,并且可以手动配置)。

A MAX_ORDER value of 11 allows 2048 pages to be allocated, which for the most usual page size of 4096 allows a maximum allocation size of 8388608 (8 MiB). MAX_ORDER值为 11 允许分配 2048 个页面,对于最常见的页面大小 4096,允许最大分配大小为 8388608 (8 MiB)。

I have no idea how to determine the DRAM row size, but it probably is not related to the system page size because the latter is determined by the architecture's MMU (and is 4096 for most architectures).我不知道如何确定 DRAM 行大小,但它可能与系统页面大小无关,因为后者由体系结构的 MMU 决定(大多数体系结构为 4096)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM