Skip to content

Commit 32a545e

Browse files
committed
new
0 parents  commit 32a545e

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

Makefile

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ifneq ($(KERNELRELEASE),)
2+
obj-m := gfn_to_pfn.o
3+
else
4+
5+
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
6+
7+
PWD := $(shell pwd)
8+
9+
default:
10+
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
11+
12+
clean:
13+
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
14+
endif

gfn_to_pfn.c

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include <linux/module.h>
2+
#include <linux/kernel.h>
3+
#include <linux/kvm_host.h>
4+
#include <linux/kvm.h>
5+
#include <linux/mm.h>
6+
#include <linux/proc_fs.h>
7+
#include <linux/uaccess.h>
8+
static struct proc_dir_entry *proc_entry;
9+
#include <asm/pgtable.h>
10+
11+
12+
13+
14+
static long get_user_page_info(struct mm_struct *mm, unsigned long va)
15+
{
16+
long ret;
17+
int locked = 0;
18+
struct page *pages[1] = { NULL };
19+
ret = get_user_pages_remote(mm, va, 1, FOLL_GET, pages, NULL);
20+
if (ret < 0) {
21+
pr_err("get_user_pages_remote failed with %ld\n", ret);
22+
return ret;
23+
}
24+
if (ret == 0) {
25+
pr_err("No pages were returned for VA 0x%lx\n", va);
26+
return 0;
27+
}
28+
struct page *page = pages[0];
29+
unsigned long pfn = page_to_pfn(page);
30+
phys_addr_t phys = PFN_PHYS(pfn);
31+
printk(KERN_INFO "Page Found for VA");
32+
printk(KERN_INFO "Physical Address:0x%llx", (unsigned long long)phys);
33+
printk(KERN_INFO "WARNING This is using PageTransHuge and PageHuge utilities to detect a hugepage i don't trust them");
34+
//Note that if a page huge is declared it's probably a huge page. But I don't quite trust a non-huge page detection to detect if it isn't yet
35+
if (PageTransHuge(page)) {
36+
printk(KERN_INFO "page is part of THP\n");
37+
} else if (PageHuge(page)) {
38+
printk(KERN_INFO "page is huge\n");
39+
} else {
40+
printk(KERN_INFO "page is not huge page\n");
41+
}
42+
put_page(page);
43+
return ret;
44+
}
45+
46+
47+
48+
static void print_gfn_to_hva(unsigned long gfn_val)
49+
{
50+
struct kvm *kvm;
51+
unsigned long hva;
52+
gfn_t gfn = (gfn_t)gfn_val;
53+
//find first kvm - this needs expanding for variable # of kvms
54+
kvm = list_first_entry_or_null(&vm_list, struct kvm, vm_list);
55+
if (!kvm) {
56+
printk(KERN_ERR "No VMs found\n");
57+
return;
58+
}
59+
printk(KERN_INFO "Found VM\n");
60+
hva = gfn_to_hva(kvm, gfn);
61+
if (kvm_is_error_hva(hva)) {
62+
printk(KERN_ERR "Error getting HVA for GFN 0x%lx\n", gfn_val);
63+
return;
64+
}
65+
printk(KERN_INFO "GFN 0x%lx maps to HVA 0x%lx\n", gfn_val, hva);
66+
get_user_page_info(kvm->mm,hva);
67+
}
68+
69+
70+
static ssize_t gfn_write(struct file *file, const char __user *ubuf,
71+
size_t count, loff_t *ppos)
72+
{
73+
//get gfn from buffer
74+
char buf[32];
75+
unsigned long gfn;
76+
if (count > sizeof(buf) - 1)
77+
return -EINVAL;
78+
if (copy_from_user(buf, ubuf, count))
79+
return -EFAULT;
80+
buf[count] = '\0';
81+
if (kstrtoul(buf, 0, &gfn))
82+
return -EINVAL;
83+
print_gfn_to_hva(gfn);
84+
return count;
85+
}
86+
87+
static const struct proc_ops gfn_fops = {
88+
.proc_write = gfn_write,
89+
};
90+
91+
static int __init gfn_module_init(void)
92+
{
93+
proc_entry = proc_create("gfn_to_hva", 0666, NULL, &gfn_fops);
94+
if (!proc_entry)
95+
return -ENOMEM;
96+
printk(KERN_INFO "GFN to HVA module loaded\n");
97+
return 0;
98+
}
99+
100+
static void __exit gfn_module_exit(void)
101+
{
102+
proc_remove(proc_entry);
103+
printk(KERN_INFO "GFN to HVA module unloaded\n");
104+
}
105+
106+
module_init(gfn_module_init);
107+
module_exit(gfn_module_exit);
108+
109+
MODULE_LICENSE("GPL");
110+
MODULE_AUTHOR("Your Name");
111+
MODULE_DESCRIPTION("GFN to HVA translation module");

0 commit comments

Comments
 (0)