-
Notifications
You must be signed in to change notification settings - Fork 304
/
phy_mem_auto_offset.h
150 lines (135 loc) · 4.8 KB
/
phy_mem_auto_offset.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef PHY_MEM_AUTO_OFFSET_H_
#define PHY_MEM_AUTO_OFFSET_H_
#include "api_proxy.h"
#include "ver_control.h"
#undef pgd_offset
#if MY_LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,84)
//来源:#define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr))
#define my_pgd_offset(pgd, addr) (pgd+pgd_index(addr))
#define my_pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
#endif
#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,10,43)
//来源:#define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr))
#define my_pgd_offset(pgd, addr) (pgd+pgd_index(addr))
#define my_pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
#endif
#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,43)
//来源:#define pgd_offset(mm, address) pgd_offset_pgd((mm)->pgd, (address))
#define my_pgd_offset(pgd, address) pgd_offset_pgd(pgd, address)
#endif
#define my_get_fs() (current_thread_info()->addr_limit)
MY_STATIC size_t g_phy_total_memory_size = 0; // 物理内存总大小
MY_STATIC int init_phy_total_memory_size(void) {
struct sysinfo si;
unsigned long mem_total, sav_total;
unsigned int bitcount = 0;
unsigned int mem_unit = 0;
if (g_phy_total_memory_size) {
return 0;
}
si_meminfo(&si);
mem_unit = si.mem_unit;
mem_total = si.totalram;
while (mem_unit > 1) {
bitcount++;
mem_unit >>= 1;
sav_total = mem_total;
mem_total <<= 1;
if (mem_total < sav_total) {
return 0;
}
}
si.totalram <<= bitcount;
g_phy_total_memory_size = __pa(si.totalram);
printk_debug(KERN_INFO "MemTotal si.totalram:%ld\n", si.totalram);
printk_debug(KERN_INFO "g_phy_total_memory_size:%ld\n", g_phy_total_memory_size);
return 0;
}
#ifdef CONFIG_USE_PAGE_TABLE_CALC_PHY_ADDR
MY_STATIC ssize_t g_pgd_offset_mm_struct = 0;
MY_STATIC bool g_init_pgd_offset_success = false;
#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,75)
MY_STATIC int init_pgd_offset(struct mm_struct *mm) {
int is_find_pgd_offset = 0;
g_init_pgd_offset_success = false;
for (g_pgd_offset_mm_struct = -40; g_pgd_offset_mm_struct <= 80; g_pgd_offset_mm_struct += 1) {
char *rp;
size_t val;
ssize_t accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct);
if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) {
return -EFAULT;
}
rp = (char*)((size_t)mm + (size_t)accurate_offset);
val = *(size_t*)(rp);
printk_debug(KERN_EMERG "init_pgd_offset %zd:%zd:%p:%ld\n", g_pgd_offset_mm_struct, accurate_offset, rp, val);
if (val == TASK_SIZE) {
g_pgd_offset_mm_struct += sizeof(unsigned long);
printk_debug(KERN_EMERG "found g_init_pgd_offset_success:%zd\n", g_pgd_offset_mm_struct);
is_find_pgd_offset = 1;
break;
}
}
if (!is_find_pgd_offset) {
printk_debug(KERN_INFO "find pgd offset failed\n");
return -ESPIPE;
}
g_init_pgd_offset_success = true;
printk_debug(KERN_INFO "g_pgd_offset_mm_struct:%zu\n", g_pgd_offset_mm_struct);
return 0;
}
#else
MY_STATIC int init_pgd_offset(struct mm_struct *mm) {
int is_find_pgd_offset = 0;
g_init_pgd_offset_success = false;
for (g_pgd_offset_mm_struct = -40; g_pgd_offset_mm_struct <= 80; g_pgd_offset_mm_struct += 1) {
char *rp;
size_t val;
ssize_t accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct);
if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) {
return -EFAULT;
}
rp = (char*)((size_t)mm + (size_t)accurate_offset);
val = *(size_t*)(rp);
printk_debug(KERN_EMERG "init_pgd_offset %zd:%zd:%p:%ld\n", g_pgd_offset_mm_struct, accurate_offset, rp, val);
if (val == TASK_SIZE) {
g_pgd_offset_mm_struct += sizeof(unsigned long);
g_pgd_offset_mm_struct += sizeof(unsigned long);
printk_debug(KERN_EMERG "found g_init_pgd_offset_success:%zd\n", g_pgd_offset_mm_struct);
is_find_pgd_offset = 1;
break;
}
}
if (!is_find_pgd_offset) {
printk_debug(KERN_INFO "find pgd offset failed\n");
return -ESPIPE;
}
g_init_pgd_offset_success = true;
printk_debug(KERN_INFO "g_pgd_offset_mm_struct:%zu\n", g_pgd_offset_mm_struct);
return 0;
}
#endif
MY_STATIC inline pgd_t *x_pgd_offset(struct mm_struct *mm, size_t addr) {
size_t pgd;
ssize_t accurate_offset;
if (g_init_pgd_offset_success == false) {
if (init_pgd_offset(mm) != 0) {
return NULL;
}
}
//精确偏移
accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct);
printk_debug(KERN_INFO "x_pgd_offset accurate_offset:%zd\n", accurate_offset);
if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) {
return NULL;
}
//拷贝到我自己的pgd指针变量里去
//写法一(可读性强)
//void * rv = (size_t*)((size_t)mm + (size_t)accurate_offset);
//pgd_t *pgd;
//memcpy(&pgd, rv, sizeof(pgd_t *));
//写法二(快些)
pgd = *(size_t*)((size_t)mm + (size_t)accurate_offset);
return my_pgd_offset((pgd_t*)pgd, addr);
}
#endif
#endif /* PHY_MEM_AUTO_OFFSET_H_ */