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 #include <linux/page.h>
13
14 #include <asm/segment.h>
15 #include <asm/io.h>
16
17
18
19
20
21
22
23 #define mem_write NULL
24
25 static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
26 {
27 unsigned long addr, pid, cr3;
28 char *tmp;
29 unsigned long pte, page;
30 int i;
31
32 if (count < 0)
33 return -EINVAL;
34 pid = inode->i_ino;
35 pid >>= 16;
36 cr3 = 0;
37 for (i = 1 ; i < NR_TASKS ; i++)
38 if (task[i] && task[i]->pid == pid) {
39 cr3 = task[i]->tss.cr3;
40 break;
41 }
42 if (!cr3)
43 return -EACCES;
44 addr = file->f_pos;
45 tmp = buf;
46 while (count > 0) {
47 if (current->signal & ~current->blocked)
48 break;
49 pte = *PAGE_DIR_OFFSET(cr3,addr);
50 if (!(pte & PAGE_PRESENT))
51 break;
52 pte &= PAGE_MASK;
53 pte += PAGE_PTR(addr);
54 page = *(unsigned long *) pte;
55 if (!(page & 1))
56 break;
57 page &= PAGE_MASK;
58 page += addr & ~PAGE_MASK;
59 i = PAGE_SIZE-(addr & ~PAGE_MASK);
60 if (i > count)
61 i = count;
62 memcpy_tofs(tmp,(void *) page,i);
63 addr += i;
64 tmp += i;
65 count -= i;
66 }
67 file->f_pos = addr;
68 return tmp-buf;
69 }
70
71 #ifndef mem_write
72
73 static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
74 {
75 unsigned long addr, pid, cr3;
76 char *tmp;
77 unsigned long pte, page;
78 int i;
79
80 if (count < 0)
81 return -EINVAL;
82 addr = file->f_pos;
83 pid = inode->i_ino;
84 pid >>= 16;
85 cr3 = 0;
86 for (i = 1 ; i < NR_TASKS ; i++)
87 if (task[i] && task[i]->pid == pid) {
88 cr3 = task[i]->tss.cr3;
89 break;
90 }
91 if (!cr3)
92 return -EACCES;
93 tmp = buf;
94 while (count > 0) {
95 if (current->signal & ~current->blocked)
96 break;
97 pte = *PAGE_DIR_OFFSET(cr3,addr);
98 if (!(pte & PAGE_PRESENT))
99 break;
100 pte &= PAGE_MASK;
101 pte += PAGE_PTR(addr);
102 page = *(unsigned long *) pte;
103 if (!(page & PAGE_PRESENT))
104 break;
105 if (!(page & 2)) {
106 do_wp_page(0,addr,current,0);
107 continue;
108 }
109 page &= PAGE_MASK;
110 page += addr & ~PAGE_MASK;
111 i = PAGE_SIZE-(addr & ~PAGE_MASK);
112 if (i > count)
113 i = count;
114 memcpy_fromfs((void *) page,tmp,i);
115 addr += i;
116 tmp += i;
117 count -= i;
118 }
119 file->f_pos = addr;
120 if (tmp != buf)
121 return tmp-buf;
122 if (current->signal & ~current->blocked)
123 return -ERESTARTSYS;
124 return 0;
125 }
126
127 #endif
128
129 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
130 {
131 switch (orig) {
132 case 0:
133 file->f_pos = offset;
134 return file->f_pos;
135 case 1:
136 file->f_pos += offset;
137 return file->f_pos;
138 default:
139 return -EINVAL;
140 }
141 }
142
143 int
144 mem_mmap(struct inode * inode, struct file * file,
145 struct vm_area_struct * vma)
146 {
147 unsigned long *src_table, *dest_table, stmp, dtmp, cr3;
148 struct vm_area_struct *src_vma = 0;
149 int i;
150
151
152
153 cr3 = 0;
154 for (i = 1 ; i < NR_TASKS ; i++)
155 if (task[i] && task[i]->pid == (inode->i_ino >> 16)) {
156 cr3 = task[i]->tss.cr3;
157 src_vma = task[i]->mm->mmap;
158 break;
159 }
160
161 if (!cr3)
162 return -EACCES;
163
164
165
166
167
168
169 stmp = vma->vm_offset;
170 while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
171 while (src_vma && stmp > src_vma->vm_end)
172 src_vma = src_vma->vm_next;
173 if (!src_vma || (src_vma->vm_flags & VM_SHM))
174 return -EINVAL;
175
176 src_table = PAGE_DIR_OFFSET(cr3, stmp);
177 if (!*src_table)
178 return -EINVAL;
179 src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp));
180 if (!*src_table)
181 return -EINVAL;
182
183 if (stmp < src_vma->vm_start) {
184 if (!(src_vma->vm_flags & VM_GROWSDOWN))
185 return -EINVAL;
186 if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur)
187 return -EINVAL;
188 }
189 stmp += PAGE_SIZE;
190 }
191
192 src_vma = task[i]->mm->mmap;
193 stmp = vma->vm_offset;
194 dtmp = vma->vm_start;
195
196 while (dtmp < vma->vm_end) {
197 while (src_vma && stmp > src_vma->vm_end)
198 src_vma = src_vma->vm_next;
199
200 src_table = PAGE_DIR_OFFSET(cr3, stmp);
201 src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp));
202
203 dest_table = PAGE_DIR_OFFSET(current->tss.cr3, dtmp);
204
205 if (!*dest_table) {
206 *dest_table = get_free_page(GFP_KERNEL);
207 if (!*dest_table) { oom(current); *dest_table=BAD_PAGE; }
208 else *dest_table |= PAGE_TABLE;
209 }
210
211 dest_table = (unsigned long *)((*dest_table & PAGE_MASK) + PAGE_PTR(dtmp));
212
213 if (!(*src_table & PAGE_PRESENT))
214 do_no_page(src_vma, stmp, PAGE_PRESENT);
215
216 if ((vma->vm_flags & VM_WRITE) && !(*src_table & PAGE_RW))
217 do_wp_page(src_vma, stmp, PAGE_RW | PAGE_PRESENT);
218
219 *src_table |= PAGE_DIRTY;
220 *dest_table = *src_table;
221 mem_map[MAP_NR(*src_table)]++;
222
223 stmp += PAGE_SIZE;
224 dtmp += PAGE_SIZE;
225 }
226
227 invalidate();
228 return 0;
229 }
230
231 static struct file_operations proc_mem_operations = {
232 mem_lseek,
233 mem_read,
234 mem_write,
235 NULL,
236 NULL,
237 NULL,
238 mem_mmap,
239 NULL,
240 NULL,
241 NULL
242 };
243
244 struct inode_operations proc_mem_inode_operations = {
245 &proc_mem_operations,
246 NULL,
247 NULL,
248 NULL,
249 NULL,
250 NULL,
251 NULL,
252 NULL,
253 NULL,
254 NULL,
255 NULL,
256 NULL,
257 NULL,
258 NULL,
259 NULL
260 };