I am trying to make a kernel module that gives me some basic information about the memory, like nodes, zones, pages, etc. I am not able to build the module, there are some errors. I am using Ubuntu 20.04. Kernel 5.8.0-55-generic.
The code is as follows:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mmzone.h>
static int __init hello_entry(void){
pg_data_t* pgdat;
for_each_online_pgdat(pgdat){
printk("KERN_ALERT" "Number of Zones: %d\n", pgdat->nr_zones);
}
printk("KERN_ALERT" "Hello World Entry!\n");
return 0;
}
static void __exit hello_exit(void){
printk("KERN_ALERT" "Hello World Exit!\n");
}
module_init(hello_entry);
module_exit(hello_exit);
Make File output:
root@madhur-VivoBook:/media/madhur/CommonSpace/Work/Linux/KernelModule# make
make -C /lib/modules/5.8.0-55-generic/build M=/media/madhur/CommonSpace/Work/Linux/KernelModule modules
make[1]: Entering directory '/usr/src/linux-headers-5.8.0-55-generic'
MODPOST /media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers
WARNING: modpost: missing MODULE_LICENSE() in /media/madhur/CommonSpace/Work/Linux/KernelModule/hello.o
ERROR: modpost: "next_online_pgdat" [/media/madhur/CommonSpace/Work/Linux/KernelModule/hello.ko] undefined!
ERROR: modpost: "first_online_pgdat" [/media/madhur/CommonSpace/Work/Linux/KernelModule/hello.ko] undefined!
make[2]: *** [scripts/Makefile.modpost:111: /media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers] Error 1
make[2]: *** Deleting file '/media/madhur/CommonSpace/Work/Linux/KernelModule/Module.symvers'
make[1]: *** [Makefile:1698: modules] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-55-generic'
make: *** [Makefile:5: all] Error 2
next_online_pgdat and first_online_pgdat are defined in the mmzone.h file, yet there is this message that they are undefined.
I am trying to write a module for the first time, so it would be very helpful if someone could suggest some resources for the Linux kernel module programming, specifically memory management. I actually want to allocate and access physical memory pages and do some stuff with them.
Update: Thanks to @Tsyvarev. Now my code looks like this:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/mmzone.h>
#include <asm/cacheflush.h>
static int __init hello_entry(void){
printk(KERN_ALERT "Hello World Entry!\n");
printk(KERN_ALERT "Page Size: %ld\n", PAGE_SIZE);
printk(KERN_ALERT "Cache Line Size: %ld\n", cache_line_size());
int i;
int number_of_pages = 3;
int* pages = (int *)alloc_pages_exact(number_of_pages * PAGE_SIZE, __GFP_DMA);
int *prev_page, *rowhammer_page, *next_page;
prev_page = pages;
rowhammer_page = prev_page + PAGE_SIZE;
next_page = rowhammer_page + PAGE_SIZE;
for(i = 0; i < PAGE_SIZE / sizeof(int); i++){
prev_page[i] = i;
rowhammer_page[i] = i;
next_page[i] = i;
}
clflush_cache_range(rowhammer_page, PAGE_SIZE);//Flush rowhammer_page from cache(Will this flush from all cache?)
int read_midvalue = rowhammer_page[PAGE_SIZE / (sizeof(int) * 2)]; //Reading the middle value present in the page
if(read_midvalue != PAGE_SIZE / (sizeof(int) * 2)){
printk(KERN_ALERT "Rowhammer Fault on access number %d\n", i);
}
return 0;
}
static void __exit hello_exit(void){
printk(KERN_ALERT "Hello World Exit!\n");
}
module_init(hello_entry);
module_exit(hello_exit);
This compiles well, but when I do insmod hello.ko, the log shows that clflush_cache_range is an unknown symbol. Here is the log:
[ 1246.489806] hello: loading out-of-tree module taints kernel.
[ 1246.489812] hello: module license 'unspecified' taints kernel.
[ 1246.489814] Disabling lock debugging due to kernel taint
[ 1246.489903] hello: module verification failed: signature and/or required key missing - tainting kernel
[ 1246.490039] hello: Unknown symbol clflush_cache_range (err -2)
I am using an x86 machine.