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