This source file includes following definitions.
- mem_read
- mem_write
- mem_lseek
- mem_mmap
1 #define THREE_LEVEL
2
3
4
5
6
7
8 #include <linux/types.h>
9 #include <linux/errno.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/mm.h>
13
14 #include <asm/page.h>
15 #include <asm/segment.h>
16 #include <asm/io.h>
17 #include <asm/pgtable.h>
18
19
20
21
22
23
24
25 #define mem_write NULL
26
27 static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
28 {
29 pgd_t *page_dir;
30 pmd_t *page_middle;
31 pte_t pte;
32 char * page;
33 struct task_struct * tsk;
34 unsigned long addr, pid;
35 char *tmp;
36 int i;
37
38 if (count < 0)
39 return -EINVAL;
40 pid = inode->i_ino;
41 pid >>= 16;
42 tsk = NULL;
43 for (i = 1 ; i < NR_TASKS ; i++)
44 if (task[i] && task[i]->pid == pid) {
45 tsk = task[i];
46 break;
47 }
48 if (!tsk)
49 return -EACCES;
50 addr = file->f_pos;
51 tmp = buf;
52 while (count > 0) {
53 if (current->signal & ~current->blocked)
54 break;
55 page_dir = pgd_offset(tsk,addr);
56 if (pgd_none(*page_dir))
57 break;
58 if (pgd_bad(*page_dir)) {
59 printk("Bad page dir entry %08lx\n", pgd_val(*page_dir));
60 pgd_clear(page_dir);
61 break;
62 }
63 page_middle = pmd_offset(page_dir,addr);
64 if (pmd_none(*page_middle))
65 break;
66 if (pmd_bad(*page_middle)) {
67 printk("Bad page middle entry %08lx\n", pmd_val(*page_middle));
68 pmd_clear(page_middle);
69 break;
70 }
71 pte = *pte_offset(page_middle,addr);
72 if (!pte_present(pte))
73 break;
74 page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
75 i = PAGE_SIZE-(addr & ~PAGE_MASK);
76 if (i > count)
77 i = count;
78 memcpy_tofs(tmp, page, i);
79 addr += i;
80 tmp += i;
81 count -= i;
82 }
83 file->f_pos = addr;
84 return tmp-buf;
85 }
86
87 #ifndef mem_write
88
89 static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
90 {
91 pgd_t *page_dir;
92 pmd_t *page_middle;
93 pte_t pte;
94 char * page;
95 struct task_struct * tsk;
96 unsigned long addr, pid;
97 char *tmp;
98 int i;
99
100 if (count < 0)
101 return -EINVAL;
102 addr = file->f_pos;
103 pid = inode->i_ino;
104 pid >>= 16;
105 tsk = NULL;
106 for (i = 1 ; i < NR_TASKS ; i++)
107 if (task[i] && task[i]->pid == pid) {
108 tsk = task[i];
109 break;
110 }
111 if (!tsk)
112 return -EACCES;
113 tmp = buf;
114 while (count > 0) {
115 if (current->signal & ~current->blocked)
116 break;
117 page_dir = pgd_offset(tsk,addr);
118 if (pgd_none(*page_dir))
119 break;
120 if (pgd_bad(*page_dir)) {
121 printk("Bad page dir entry %08lx\n", pgd_val(*page_dir));
122 pgd_clear(page_dir);
123 break;
124 }
125 page_middle = pmd_offset(page_dir,addr);
126 if (pmd_none(*page_middle))
127 break;
128 if (pmd_bad(*page_middle)) {
129 printk("Bad page middle entry %08lx\n", pmd_val(*page_middle));
130 pmd_clear(page_middle);
131 break;
132 }
133 pte = *pte_offset(page_middle,addr);
134 if (!pte_present(pte))
135 break;
136 if (!pte_write(pte))
137 break;
138 page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
139 i = PAGE_SIZE-(addr & ~PAGE_MASK);
140 if (i > count)
141 i = count;
142 memcpy_fromfs(page, tmp, i);
143 addr += i;
144 tmp += i;
145 count -= i;
146 }
147 file->f_pos = addr;
148 if (tmp != buf)
149 return tmp-buf;
150 if (current->signal & ~current->blocked)
151 return -ERESTARTSYS;
152 return 0;
153 }
154
155 #endif
156
157 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
158 {
159 switch (orig) {
160 case 0:
161 file->f_pos = offset;
162 return file->f_pos;
163 case 1:
164 file->f_pos += offset;
165 return file->f_pos;
166 default:
167 return -EINVAL;
168 }
169 }
170
171
172
173
174 int mem_mmap(struct inode * inode, struct file * file,
175 struct vm_area_struct * vma)
176 {
177 struct task_struct *tsk;
178 pgd_t *src_dir, *dest_dir;
179 pmd_t *src_middle, *dest_middle;
180 pte_t *src_table, *dest_table;
181 unsigned long stmp, dtmp;
182 struct vm_area_struct *src_vma = NULL;
183 int i;
184
185
186
187 tsk = NULL;
188 for (i = 1 ; i < NR_TASKS ; i++)
189 if (task[i] && task[i]->pid == (inode->i_ino >> 16)) {
190 tsk = task[i];
191 break;
192 }
193
194 if (!tsk)
195 return -EACCES;
196
197
198
199
200
201
202 src_vma = tsk->mm->mmap;
203 stmp = vma->vm_offset;
204 while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
205 while (src_vma && stmp > src_vma->vm_end)
206 src_vma = src_vma->vm_next;
207 if (!src_vma || (src_vma->vm_flags & VM_SHM))
208 return -EINVAL;
209
210 src_dir = pgd_offset(tsk, stmp);
211 if (pgd_none(*src_dir))
212 return -EINVAL;
213 if (pgd_bad(*src_dir)) {
214 printk("Bad source page dir entry %08lx\n", pgd_val(*src_dir));
215 return -EINVAL;
216 }
217 src_middle = pmd_offset(src_dir, stmp);
218 if (pmd_none(*src_middle))
219 return -EINVAL;
220 if (pmd_bad(*src_middle)) {
221 printk("Bad source page middle entry %08lx\n", pmd_val(*src_middle));
222 return -EINVAL;
223 }
224 src_table = pte_offset(src_middle, stmp);
225 if (pte_none(*src_table))
226 return -EINVAL;
227
228 if (stmp < src_vma->vm_start) {
229 if (!(src_vma->vm_flags & VM_GROWSDOWN))
230 return -EINVAL;
231 if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur)
232 return -EINVAL;
233 }
234 stmp += PAGE_SIZE;
235 }
236
237 src_vma = tsk->mm->mmap;
238 stmp = vma->vm_offset;
239 dtmp = vma->vm_start;
240
241 while (dtmp < vma->vm_end) {
242 while (src_vma && stmp > src_vma->vm_end)
243 src_vma = src_vma->vm_next;
244
245 src_dir = pgd_offset(tsk, stmp);
246 src_middle = pmd_offset(src_dir, stmp);
247 src_table = pte_offset(src_middle, stmp);
248
249 dest_dir = pgd_offset(current, dtmp);
250 dest_middle = pmd_alloc(dest_dir, dtmp);
251 if (!dest_middle)
252 return -ENOMEM;
253 dest_table = pte_alloc(dest_middle, dtmp);
254 if (!dest_table)
255 return -ENOMEM;
256
257 if (!pte_present(*src_table))
258 do_no_page(src_vma, stmp, 1);
259
260 if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table))
261 do_wp_page(src_vma, stmp, 1);
262
263 *src_table = pte_mkdirty(*src_table);
264 *dest_table = *src_table;
265 mem_map[MAP_NR(pte_page(*src_table))]++;
266
267 stmp += PAGE_SIZE;
268 dtmp += PAGE_SIZE;
269 }
270
271 invalidate();
272 return 0;
273 }
274
275 static struct file_operations proc_mem_operations = {
276 mem_lseek,
277 mem_read,
278 mem_write,
279 NULL,
280 NULL,
281 NULL,
282 mem_mmap,
283 NULL,
284 NULL,
285 NULL
286 };
287
288 struct inode_operations proc_mem_inode_operations = {
289 &proc_mem_operations,
290 NULL,
291 NULL,
292 NULL,
293 NULL,
294 NULL,
295 NULL,
296 NULL,
297 NULL,
298 NULL,
299 NULL,
300 NULL,
301 NULL,
302 NULL,
303 NULL
304 };