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