Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 018
019 #include <sos/assert.h> 019 #include <sos/assert.h>
020 #include <sos/kmalloc.h> 020 #include <sos/kmalloc.h>
021 #include <sos/physmem.h> 021 #include <sos/physmem.h>
022 #include <hwcore/paging.h> 022 #include <hwcore/paging.h>
023 #include <sos/kmem_slab.h> 023 #include <sos/kmem_slab.h>
024 #include <sos/list.h> 024 #include <sos/list.h>
025 #include <hwcore/paging.h> 025 #include <hwcore/paging.h>
>> 026 #include <sos/uaccess.h>
>> 027 #include <sos/chardev.h>
>> 028 #include <drivers/devices.h>
026 029
027 #include "zero.h" 030 #include "zero.h"
028 031
029 032
030 033
031 034
032 035
033 struct zero_mapped_page 036 struct zero_mapped_page
034 { 037 {
035 sos_uoffset_t page_id; 038 sos_uoffset_t page_id;
036 sos_paddr_t ppage_paddr; 039 sos_paddr_t ppage_paddr;
037 040
038 struct zero_mapped_page *prev, *next; 041 struct zero_mapped_page *prev, *next;
039 }; 042 };
040 043
041 struct sos_kslab_cache * cache_of_zero_mapped_ 044 struct sos_kslab_cache * cache_of_zero_mapped_pages;
042 045
043 046
044 047
045 048
046 049
047 struct zero_mapped_resource 050 struct zero_mapped_resource
048 { 051 {
049 int ref_cnt; 052 int ref_cnt;
050 053
051 054
052 055
053 056
054 057
055 struct zero_mapped_page *list_mapped_pages; 058 struct zero_mapped_page *list_mapped_pages;
056 059
057 struct sos_umem_vmm_mapped_resource mr; 060 struct sos_umem_vmm_mapped_resource mr;
058 }; 061 };
059 062
060 063
>> 064
>> 065
>> 066 static struct sos_chardev_ops dev_zero_fs_ops;
>> 067
>> 068
061 069
062 070
063 static sos_ret_t insert_anonymous_physpage(str 071 static sos_ret_t insert_anonymous_physpage(struct zero_mapped_resource *mr,
064 sos 072 sos_paddr_t ppage_paddr,
065 sos 073 sos_uoffset_t page_id);
066 074
067 075
068 076
069 077
070 static sos_paddr_t lookup_anonymous_physpage(s 078 static sos_paddr_t lookup_anonymous_physpage(struct zero_mapped_resource *mr,
071 s 079 sos_uoffset_t page_id);
072 080
073 081
074 sos_ret_t sos_dev_zero_subsystem_setup() 082 sos_ret_t sos_dev_zero_subsystem_setup()
075 { 083 {
>> 084 sos_ret_t retval;
>> 085
076 cache_of_zero_mapped_pages = 086 cache_of_zero_mapped_pages =
077 sos_kmem_cache_create("shared anonymous ma 087 sos_kmem_cache_create("shared anonymous mappings",
078 sizeof(struct zero_m 088 sizeof(struct zero_mapped_page),
079 1, 0, 089 1, 0,
080 SOS_KSLAB_CREATE_MAP 090 SOS_KSLAB_CREATE_MAP | SOS_KSLAB_CREATE_ZERO);
081 if (! cache_of_zero_mapped_pages) 091 if (! cache_of_zero_mapped_pages)
082 return -SOS_ENOMEM; 092 return -SOS_ENOMEM;
083 093
>> 094 retval = sos_chardev_register_class(SOS_CHARDEV_ZERO_MAJOR,
>> 095 & dev_zero_fs_ops,
>> 096 NULL);
>> 097 if (SOS_OK != retval)
>> 098 {
>> 099 sos_kmem_cache_destroy(cache_of_zero_mapped_pages);
>> 100 return retval;
>> 101 }
>> 102
084 return SOS_OK; 103 return SOS_OK;
085 } 104 }
086 105
087 106
088 107
089 108
090 static void zero_ref(struct sos_umem_vmm_vr * 109 static void zero_ref(struct sos_umem_vmm_vr * vr)
091 { 110 {
092 111
093 struct zero_mapped_resource * zero_resource; 112 struct zero_mapped_resource * zero_resource;
094 zero_resource 113 zero_resource
095 = (struct zero_mapped_resource*) 114 = (struct zero_mapped_resource*)
096 sos_umem_vmm_get_mapped_resource_of_vr(vr) 115 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
097 116
098 117
099 zero_resource->ref_cnt ++; 118 zero_resource->ref_cnt ++;
100 } 119 }
101 120
102 121
103 122
104 123
105 static void zero_unref(struct sos_umem_vmm_vr 124 static void zero_unref(struct sos_umem_vmm_vr * vr)
106 { 125 {
107 126
108 struct zero_mapped_resource * zero_resource; 127 struct zero_mapped_resource * zero_resource;
109 zero_resource 128 zero_resource
110 = (struct zero_mapped_resource*) 129 = (struct zero_mapped_resource*)
111 sos_umem_vmm_get_mapped_resource_of_vr(vr) 130 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
112 !! 131
113 132
114 SOS_ASSERT_FATAL(zero_resource->ref_cnt > 0) 133 SOS_ASSERT_FATAL(zero_resource->ref_cnt > 0);
115 zero_resource->ref_cnt --; 134 zero_resource->ref_cnt --;
116 135
117 136
118 if (zero_resource->ref_cnt == 0) 137 if (zero_resource->ref_cnt == 0)
119 { 138 {
120 139
121 struct zero_mapped_page *zmp; 140 struct zero_mapped_page *zmp;
122 list_collapse(zero_resource->list_mapped 141 list_collapse(zero_resource->list_mapped_pages, zmp)
123 { 142 {
124 !! 143
125 !! 144 sos_physmem_unref_physpage(zmp->ppage_paddr);
126 <<
127 sos_kfree((sos_vaddr_t)zmp); 145 sos_kfree((sos_vaddr_t)zmp);
128 } 146 }
129 147
130 sos_kfree((sos_vaddr_t)zero_resource); 148 sos_kfree((sos_vaddr_t)zero_resource);
131 } 149 }
132 } 150 }
133 151
134 152
135 153
136 154
137 static sos_ret_t zero_page_in(struct sos_umem_ 155 static sos_ret_t zero_page_in(struct sos_umem_vmm_vr * vr,
138 sos_uaddr_t uadd 156 sos_uaddr_t uaddr,
139 sos_bool_t write 157 sos_bool_t write_access)
140 { 158 {
141 sos_ret_t retval = SOS_OK; 159 sos_ret_t retval = SOS_OK;
142 sos_paddr_t ppage_paddr; 160 sos_paddr_t ppage_paddr;
143 sos_uoffset_t required_page_id; 161 sos_uoffset_t required_page_id;
144 struct zero_mapped_resource * zero_resource; 162 struct zero_mapped_resource * zero_resource;
145 sos_ui32_t vr_prot, vr_flags; 163 sos_ui32_t vr_prot, vr_flags;
146 164
147 165
148 zero_resource 166 zero_resource
149 = (struct zero_mapped_resource*) 167 = (struct zero_mapped_resource*)
150 sos_umem_vmm_get_mapped_resource_of_vr(vr) 168 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
151 169
152 170
153 vr_prot = sos_umem_vmm_get_prot_of_vr(vr); 171 vr_prot = sos_umem_vmm_get_prot_of_vr(vr);
154 vr_flags = sos_umem_vmm_get_flags_of_vr(vr); 172 vr_flags = sos_umem_vmm_get_flags_of_vr(vr);
155 173
156 174
157 required_page_id = SOS_PAGE_ALIGN_INF(uaddr) 175 required_page_id = SOS_PAGE_ALIGN_INF(uaddr)
158 - sos_umem_vmm_get_start_of_vr(vr) 176 - sos_umem_vmm_get_start_of_vr(vr)
159 + sos_umem_vmm_get_offset_in_resource(vr); 177 + sos_umem_vmm_get_offset_in_resource(vr);
160 178
161 179
162 180
163 if (vr_flags & SOS_VR_MAP_SHARED) 181 if (vr_flags & SOS_VR_MAP_SHARED)
164 { 182 {
165 ppage_paddr = lookup_anonymous_physpage( 183 ppage_paddr = lookup_anonymous_physpage(zero_resource, required_page_id);
166 if (NULL != (void*)ppage_paddr) 184 if (NULL != (void*)ppage_paddr)
167 { 185 {
168 retval = sos_paging_map(ppage_paddr, 186 retval = sos_paging_map(ppage_paddr,
169 SOS_PAGE_ALI 187 SOS_PAGE_ALIGN_INF(uaddr),
170 TRUE, 188 TRUE,
171 vr_prot); 189 vr_prot);
>> 190
172 return retval; 191 return retval;
173 } 192 }
174 } 193 }
175 194
176 195
177 196
178 197
179 if (write_access) 198 if (write_access)
180 { 199 {
181 200
182 ppage_paddr = sos_physmem_ref_physpage_n 201 ppage_paddr = sos_physmem_ref_physpage_new(FALSE);
183 if (! ppage_paddr) 202 if (! ppage_paddr)
184 return -SOS_ENOMEM; 203 return -SOS_ENOMEM;
185 !! 204
186 retval = sos_paging_map(ppage_paddr, 205 retval = sos_paging_map(ppage_paddr,
187 SOS_PAGE_ALIGN_I 206 SOS_PAGE_ALIGN_INF(uaddr),
188 TRUE, 207 TRUE,
189 vr_prot); 208 vr_prot);
190 if (SOS_OK != retval) 209 if (SOS_OK != retval)
191 { 210 {
192 sos_physmem_unref_physpage(ppage_pad 211 sos_physmem_unref_physpage(ppage_paddr);
193 return retval; 212 return retval;
194 } 213 }
195 214
196 memset((void*)SOS_PAGE_ALIGN_INF(uaddr), 215 memset((void*)SOS_PAGE_ALIGN_INF(uaddr), 0x0, SOS_PAGE_SIZE);
197 216
198 217
199 218
200 if (vr_flags & SOS_VR_MAP_SHARED) 219 if (vr_flags & SOS_VR_MAP_SHARED)
201 insert_anonymous_physpage(zero_resourc 220 insert_anonymous_physpage(zero_resource, ppage_paddr,
202 required_pag 221 required_page_id);
203 222
204 sos_physmem_unref_physpage(ppage_paddr); 223 sos_physmem_unref_physpage(ppage_paddr);
205 } 224 }
206 else 225 else
207 { 226 {
208 227
209 228
210 retval = sos_paging_map(sos_zero_page, !! 229 retval = sos_paging_map(sos_zero_physpage,
211 SOS_PAGE_ALIGN_I 230 SOS_PAGE_ALIGN_INF(uaddr),
212 TRUE, 231 TRUE,
213 SOS_VM_MAP_PROT_ 232 SOS_VM_MAP_PROT_READ);
214 } 233 }
215 234
216 return retval; 235 return retval;
217 } 236 }
218 237
219 238
220 239
221 static struct sos_umem_vmm_vr_ops zero_ops = ( 240 static struct sos_umem_vmm_vr_ops zero_ops = (struct sos_umem_vmm_vr_ops)
222 { 241 {
223 .ref = zero_ref, 242 .ref = zero_ref,
224 .unref = zero_unref, 243 .unref = zero_unref,
225 .page_in = zero_page_in, 244 .page_in = zero_page_in,
226 .unmap = NULL 245 .unmap = NULL
227 }; 246 };
228 247
229 248
230 249
231 static sos_ret_t zero_mmap(struct sos_umem_vmm 250 static sos_ret_t zero_mmap(struct sos_umem_vmm_vr *vr)
232 { 251 {
233 return sos_umem_vmm_set_ops_of_vr(vr, &zero_ 252 return sos_umem_vmm_set_ops_of_vr(vr, &zero_ops);
234 } 253 }
235 254
236 255
237 256
238 257
239 sos_ret_t sos_dev_zero_map(struct sos_umem_vmm 258 sos_ret_t sos_dev_zero_map(struct sos_umem_vmm_as * dest_as,
240 sos_uaddr_t *uaddr, 259 sos_uaddr_t *uaddr,
241 sos_size_t size, 260 sos_size_t size,
242 sos_ui32_t access_r 261 sos_ui32_t access_rights,
243 sos_ui32_t flags) 262 sos_ui32_t flags)
244 { 263 {
245 sos_ret_t retval; 264 sos_ret_t retval;
246 struct zero_mapped_resource * zero_resource; 265 struct zero_mapped_resource * zero_resource;
247 266
248 zero_resource 267 zero_resource
249 = (struct zero_mapped_resource*) sos_kmall 268 = (struct zero_mapped_resource*) sos_kmalloc(sizeof(*zero_resource), 0);
250 if (! zero_resource) 269 if (! zero_resource)
251 return -SOS_ENOMEM; 270 return -SOS_ENOMEM;
252 271
253 memset(zero_resource, 0x0, sizeof(*zero_reso 272 memset(zero_resource, 0x0, sizeof(*zero_resource));
254 zero_resource->mr.allowed_access_rights 273 zero_resource->mr.allowed_access_rights
255 = SOS_VM_MAP_PROT_READ 274 = SOS_VM_MAP_PROT_READ
256 | SOS_VM_MAP_PROT_WRITE 275 | SOS_VM_MAP_PROT_WRITE
257 | SOS_VM_MAP_PROT_EXEC; 276 | SOS_VM_MAP_PROT_EXEC;
258 zero_resource->mr.flags |= SOS_MAPPE 277 zero_resource->mr.flags |= SOS_MAPPED_RESOURCE_ANONYMOUS;
259 zero_resource->mr.custom_data = zero_reso 278 zero_resource->mr.custom_data = zero_resource;
260 zero_resource->mr.mmap = zero_mmap 279 zero_resource->mr.mmap = zero_mmap;
261 280
262 retval = sos_umem_vmm_map(dest_as, uaddr, si 281 retval = sos_umem_vmm_map(dest_as, uaddr, size,
263 access_rights, fla 282 access_rights, flags,
264 &zero_resource->mr 283 &zero_resource->mr, 0);
265 if (SOS_OK != retval) 284 if (SOS_OK != retval)
266 { 285 {
267 sos_kfree((sos_vaddr_t)zero_resource); 286 sos_kfree((sos_vaddr_t)zero_resource);
268 return retval; 287 return retval;
269 } 288 }
270 289
271 return SOS_OK; 290 return SOS_OK;
272 } 291 }
273 292
274 293
275 static sos_ret_t insert_anonymous_physpage(str 294 static sos_ret_t insert_anonymous_physpage(struct zero_mapped_resource *mr,
276 sos 295 sos_paddr_t ppage_paddr,
277 sos 296 sos_uoffset_t page_id)
278 { 297 {
279 struct zero_mapped_page * zmp 298 struct zero_mapped_page * zmp
280 = (struct zero_mapped_page*)sos_kmem_cache 299 = (struct zero_mapped_page*)sos_kmem_cache_alloc(cache_of_zero_mapped_pages,
281 300 0);
282 if (! zmp) 301 if (! zmp)
283 return -SOS_ENOMEM; 302 return -SOS_ENOMEM;
284 303
285 zmp->page_id = page_id; 304 zmp->page_id = page_id;
286 zmp->ppage_paddr = ppage_paddr; 305 zmp->ppage_paddr = ppage_paddr;
287 306
288 list_add_head(mr->list_mapped_pages, zmp); 307 list_add_head(mr->list_mapped_pages, zmp);
>> 308 sos_physmem_ref_physpage_at(ppage_paddr);
289 return SOS_OK; 309 return SOS_OK;
290 } 310 }
291 311
292 312
293 static sos_paddr_t lookup_anonymous_physpage(s 313 static sos_paddr_t lookup_anonymous_physpage(struct zero_mapped_resource *mr,
294 so 314 sos_uoffset_t page_id)
295 { 315 {
296 struct zero_mapped_page * zmp; 316 struct zero_mapped_page * zmp;
297 int nb_elts; 317 int nb_elts;
298 318
299 list_foreach_forward(mr->list_mapped_pages, 319 list_foreach_forward(mr->list_mapped_pages, zmp, nb_elts)
300 { 320 {
301 if (zmp->page_id == page_id) 321 if (zmp->page_id == page_id)
302 return zmp->ppage_paddr; 322 return zmp->ppage_paddr;
303 } 323 }
304 324
305 return (sos_paddr_t)NULL; 325 return (sos_paddr_t)NULL;
306 } 326 }
>> 327
>> 328
>> 329
>> 330
>> 331
>> 332 static sos_ret_t dev_zero_fs_open(struct sos_fs_node * fsnode,
>> 333 struct sos_fs_opened_file * of,
>> 334 void * chardev_class_custom_data)
>> 335 {
>> 336
>> 337 if ( (SOS_CHARDEV_NULL_MINOR != fsnode->dev_id.device_instance)
>> 338 && (SOS_CHARDEV_ZERO_MINOR != fsnode->dev_id.device_instance) )
>> 339 return -SOS_ENODEV;
>> 340
>> 341 return SOS_OK;
>> 342 }
>> 343
>> 344
>> 345 static sos_ret_t dev_zero_fs_seek(struct sos_fs_opened_file *this,
>> 346 sos_lsoffset_t offset,
>> 347 sos_seek_whence_t whence,
>> 348 sos_lsoffset_t * result_position)
>> 349 {
>> 350
>> 351 sos_lsoffset_t ref_offs;
>> 352
>> 353 *result_position = this->position;
>> 354 switch (whence)
>> 355 {
>> 356 case SOS_SEEK_SET:
>> 357 ref_offs = 0;
>> 358 break;
>> 359
>> 360 case SOS_SEEK_CUR:
>> 361 ref_offs = this->position;
>> 362 break;
>> 363
>> 364 case SOS_SEEK_END:
>> 365 return -SOS_ENOSUP;
>> 366 break;
>> 367
>> 368 default:
>> 369 return -SOS_EINVAL;
>> 370 }
>> 371
>> 372 if (offset < -ref_offs)
>> 373 return -SOS_EINVAL;
>> 374
>> 375 this->position = ref_offs + offset;
>> 376 *result_position = this->position;
>> 377 return SOS_OK;
>> 378 }
>> 379
>> 380
>> 381 static sos_ret_t dev_zero_fs_read(struct sos_fs_opened_file *this,
>> 382 sos_uaddr_t dest_buf,
>> 383 sos_size_t * len)
>> 384 {
>> 385 struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(this->direntry);
>> 386 sos_size_t offs, rdlen;
>> 387
>> 388
>> 389 if (SOS_CHARDEV_NULL_MINOR == fsnode->dev_id.device_instance)
>> 390 {
>> 391 *len = 0;
>> 392 return SOS_OK;
>> 393 }
>> 394
>> 395
>> 396
>> 397 for (rdlen = offs = 0 ; offs < *len ; offs += SOS_PAGE_SIZE)
>> 398 {
>> 399 sos_size_t retval, memcpy_len = SOS_PAGE_SIZE;
>> 400 if (offs + memcpy_len > *len)
>> 401 memcpy_len = *len - offs;
>> 402
>> 403 retval = sos_memcpy_to_user(dest_buf + offs, sos_zero_kernelpage,
>> 404 memcpy_len);
>> 405 if (retval < 0)
>> 406 break;
>> 407
>> 408 rdlen += retval;
>> 409 if (retval != memcpy_len)
>> 410 break;
>> 411 }
>> 412
>> 413
>> 414 *len = rdlen;
>> 415 this->position += rdlen;
>> 416 return SOS_OK;
>> 417 }
>> 418
>> 419
>> 420 static sos_ret_t dev_zero_fs_write(struct sos_fs_opened_file *this,
>> 421 sos_uaddr_t src_buf,
>> 422 sos_size_t * len)
>> 423 {
>> 424
>> 425 this->position += *len;
>> 426 return SOS_OK;
>> 427 }
>> 428
>> 429
>> 430 static sos_ret_t dev_zero_fs_mmap(struct sos_fs_opened_file *this,
>> 431 sos_uaddr_t *uaddr, sos_size_t size,
>> 432 sos_ui32_t access_rights,
>> 433 sos_ui32_t flags,
>> 434 sos_luoffset_t offset)
>> 435 {
>> 436 return sos_dev_zero_map(sos_process_get_address_space(this->owner),
>> 437 uaddr, size, access_rights, flags);
>> 438 }
>> 439
>> 440
>> 441 static struct sos_chardev_ops dev_zero_fs_ops
>> 442 = (struct sos_chardev_ops) {
>> 443 .open = dev_zero_fs_open,
>> 444 .close = NULL,
>> 445 .seek = dev_zero_fs_seek,
>> 446 .read = dev_zero_fs_read,
>> 447 .write = dev_zero_fs_write,
>> 448 .mmap = dev_zero_fs_mmap,
>> 449 .fcntl = NULL,
>> 450 .ioctl = NULL
>> 451 };