Changeset 7aaed09 in mainline for kernel/generic/src
- Timestamp:
- 2011-12-18T14:02:30Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c868e2d
- Parents:
- 3b71e84d (diff), 1761268 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- kernel/generic/src
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/ddi.c
r3b71e84d r7aaed09 45 45 #include <mm/frame.h> 46 46 #include <mm/as.h> 47 #include <mm/page.h> 47 48 #include <synch/mutex.h> 48 49 #include <syscall/copy.h> … … 52 53 #include <errno.h> 53 54 #include <trace.h> 55 #include <bitops.h> 54 56 55 57 /** This lock protects the parea_btree. */ … … 87 89 /** Map piece of physical memory into virtual address space of current task. 88 90 * 89 * @param p fPhysical address of the starting frame.90 * @param v pVirtual address of the starting page.91 * @param phys Physical address of the starting frame. 92 * @param virt Virtual address of the starting page. 91 93 * @param pages Number of pages to map. 92 94 * @param flags Address space area flags for the mapping. 93 95 * 94 * @return 0 on success, EPERM if the caller lacks capabilities to use this 95 * syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there 96 * is no task matching the specified ID or the physical address space 97 * is not enabled for mapping and ENOMEM if there was a problem in 98 * creating address space area. 99 * 100 */ 101 NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, 96 * @return EOK on success. 97 * @return EPERM if the caller lacks capabilities to use this syscall. 98 * @return EBADMEM if phys or virt is not page aligned. 99 * @return ENOENT if there is no task matching the specified ID or 100 * the physical address space is not enabled for mapping. 101 * @return ENOMEM if there was a problem in creating address space area. 102 * 103 */ 104 NO_TRACE static int ddi_physmem_map(uintptr_t phys, uintptr_t virt, size_t pages, 102 105 unsigned int flags) 103 106 { 104 107 ASSERT(TASK); 105 108 106 if ((p f% FRAME_SIZE) != 0)109 if ((phys % FRAME_SIZE) != 0) 107 110 return EBADMEM; 108 111 109 if ((v p% PAGE_SIZE) != 0)112 if ((virt % PAGE_SIZE) != 0) 110 113 return EBADMEM; 111 114 … … 118 121 119 122 mem_backend_data_t backend_data; 120 backend_data.base = p f;123 backend_data.base = phys; 121 124 backend_data.frames = pages; 122 125 … … 129 132 btree_node_t *nodep; 130 133 parea_t *parea = (parea_t *) btree_search(&parea_btree, 131 (btree_key_t) p f, &nodep);134 (btree_key_t) phys, &nodep); 132 135 133 136 if ((parea != NULL) && (parea->frames >= pages)) { … … 149 152 150 153 irq_spinlock_lock(&zones.lock, true); 151 size_t znum = find_zone(ADDR2PFN(p f), pages, 0);154 size_t znum = find_zone(ADDR2PFN(phys), pages, 0); 152 155 153 156 if (znum == (size_t) -1) { … … 182 185 183 186 map: 184 if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,187 if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages), virt, 185 188 AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) { 186 189 /* … … 253 256 /** Wrapper for SYS_PHYSMEM_MAP syscall. 254 257 * 255 * @param phys _basePhysical base address to map256 * @param virt _baseDestination virtual address258 * @param phys Physical base address to map 259 * @param virt Destination virtual address 257 260 * @param pages Number of pages 258 261 * @param flags Flags of newly mapped pages … … 261 264 * 262 265 */ 263 sysarg_t sys_physmem_map( sysarg_t phys_base, sysarg_t virt_base,264 s ysarg_t pages, sysarg_t flags)265 { 266 return (sysarg_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,267 FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),268 (size_t) pages, (int)flags);266 sysarg_t sys_physmem_map(uintptr_t phys, uintptr_t virt, 267 size_t pages, unsigned int flags) 268 { 269 return (sysarg_t) 270 ddi_physmem_map(ALIGN_DOWN(phys, FRAME_SIZE), 271 ALIGN_DOWN(virt, PAGE_SIZE), pages, flags); 269 272 } 270 273 … … 287 290 } 288 291 292 NO_TRACE static int dmamem_map(uintptr_t virt, size_t size, 293 unsigned int map_flags, unsigned int flags, void **phys) 294 { 295 ASSERT(TASK); 296 297 if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0) { 298 // TODO: implement locking of non-anonymous mapping 299 return page_find_mapping(virt, phys); 300 } else { 301 // TODO: implement locking 302 303 if ((virt % PAGE_SIZE) != 0) 304 return EBADMEM; 305 306 size_t pages = SIZE2FRAMES(size); 307 uint8_t order; 308 309 /* We need the 2^order >= pages */ 310 if (pages == 1) 311 order = 0; 312 else 313 order = fnzb(pages - 1) + 1; 314 315 *phys = frame_alloc_noreserve(order, 0); 316 if (*phys == NULL) 317 return ENOMEM; 318 319 mem_backend_data_t backend_data; 320 backend_data.base = (uintptr_t) *phys; 321 backend_data.frames = pages; 322 323 if (!as_area_create(TASK->as, map_flags, size, virt, 324 AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) { 325 frame_free_noreserve((uintptr_t) *phys); 326 return ENOMEM; 327 } 328 329 return EOK; 330 } 331 } 332 333 NO_TRACE static int dmamem_unmap(uintptr_t virt, size_t size, 334 unsigned int flags) 335 { 336 // TODO: implement unlocking & unmap 337 return EOK; 338 } 339 340 sysarg_t sys_dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags, 341 unsigned int flags, void *phys_ptr) 342 { 343 void *phys; 344 int rc = dmamem_map(virt, size, map_flags, flags, &phys); 345 if (rc != EOK) 346 return rc; 347 348 rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys)); 349 if (rc != EOK) { 350 dmamem_unmap(virt, size, flags); 351 return rc; 352 } 353 354 return EOK; 355 } 356 357 sysarg_t sys_dmamem_unmap(uintptr_t virt, size_t size, unsigned int flags) 358 { 359 return dmamem_unmap(virt, size, flags); 360 } 361 289 362 /** @} 290 363 */ -
kernel/generic/src/ipc/irq.c
r3b71e84d r7aaed09 365 365 return IRQ_DECLINE; 366 366 367 #define CMD_MEM_READ(target) \368 do { \369 void *va = code->cmds[i].addr; \370 if (AS != irq->driver_as) \371 as_switch(AS, irq->driver_as); \372 memcpy_from_uspace(&target, va, (sizeof(target))); \373 if (dstarg) \374 scratch[dstarg] = target; \375 } while(0)376 377 #define CMD_MEM_WRITE(val) \378 do { \379 void *va = code->cmds[i].addr; \380 if (AS != irq->driver_as) \381 as_switch(AS, irq->driver_as); \382 memcpy_to_uspace(va, &val, sizeof(val)); \383 } while (0)384 385 367 as_t *current_as = AS; 386 size_t i; 387 for (i = 0; i < code->cmdcount; i++) { 368 if (current_as != irq->driver_as) 369 as_switch(AS, irq->driver_as); 370 371 for (size_t i = 0; i < code->cmdcount; i++) { 388 372 uint32_t dstval; 373 void *va; 374 uint8_t val8; 375 uint16_t val16; 376 uint32_t val32; 377 389 378 uintptr_t srcarg = code->cmds[i].srcarg; 390 379 uintptr_t dstarg = code->cmds[i].dstarg; … … 442 431 } 443 432 break; 444 case CMD_MEM_READ_8: { 445 uint8_t val; 446 CMD_MEM_READ(val); 447 break; 448 } 449 case CMD_MEM_READ_16: { 450 uint16_t val; 451 CMD_MEM_READ(val); 452 break; 453 } 454 case CMD_MEM_READ_32: { 455 uint32_t val; 456 CMD_MEM_READ(val); 457 break; 458 } 459 case CMD_MEM_WRITE_8: { 460 uint8_t val = code->cmds[i].value; 461 CMD_MEM_WRITE(val); 462 break; 463 } 464 case CMD_MEM_WRITE_16: { 465 uint16_t val = code->cmds[i].value; 466 CMD_MEM_WRITE(val); 467 break; 468 } 469 case CMD_MEM_WRITE_32: { 470 uint32_t val = code->cmds[i].value; 471 CMD_MEM_WRITE(val); 472 break; 473 } 433 case CMD_MEM_READ_8: 434 va = code->cmds[i].addr; 435 memcpy_from_uspace(&val8, va, sizeof(val8)); 436 if (dstarg) 437 scratch[dstarg] = val8; 438 break; 439 case CMD_MEM_READ_16: 440 va = code->cmds[i].addr; 441 memcpy_from_uspace(&val16, va, sizeof(val16)); 442 if (dstarg) 443 scratch[dstarg] = val16; 444 break; 445 case CMD_MEM_READ_32: 446 va = code->cmds[i].addr; 447 memcpy_from_uspace(&val32, va, sizeof(val32)); 448 if (dstarg) 449 scratch[dstarg] = val32; 450 break; 451 case CMD_MEM_WRITE_8: 452 val8 = code->cmds[i].value; 453 va = code->cmds[i].addr; 454 memcpy_to_uspace(va, &val8, sizeof(val8)); 455 break; 456 case CMD_MEM_WRITE_16: 457 val16 = code->cmds[i].value; 458 va = code->cmds[i].addr; 459 memcpy_to_uspace(va, &val16, sizeof(val16)); 460 break; 461 case CMD_MEM_WRITE_32: 462 val32 = code->cmds[i].value; 463 va = code->cmds[i].addr; 464 memcpy_to_uspace(va, &val32, sizeof(val32)); 465 break; 474 466 case CMD_MEM_WRITE_A_8: 475 467 if (srcarg) { 476 uint8_t val = scratch[srcarg]; 477 CMD_MEM_WRITE(val); 468 val8 = scratch[srcarg]; 469 va = code->cmds[i].addr; 470 memcpy_to_uspace(va, &val8, sizeof(val8)); 478 471 } 479 472 break; 480 473 case CMD_MEM_WRITE_A_16: 481 474 if (srcarg) { 482 uint16_t val = scratch[srcarg]; 483 CMD_MEM_WRITE(val); 475 val16 = scratch[srcarg]; 476 va = code->cmds[i].addr; 477 memcpy_to_uspace(va, &val16, sizeof(val16)); 484 478 } 485 479 break; 486 480 case CMD_MEM_WRITE_A_32: 487 481 if (srcarg) { 488 uint32_t val = scratch[srcarg]; 489 CMD_MEM_WRITE(val); 482 val32 = scratch[srcarg]; 483 va = code->cmds[i].addr; 484 memcpy_to_uspace(va, &val32, sizeof(val32)); 490 485 } 491 486 break; … … 513 508 } 514 509 } 510 515 511 if (AS != current_as) 516 512 as_switch(AS, current_as); -
kernel/generic/src/ipc/sysipc.c
r3b71e84d r7aaed09 278 278 } 279 279 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) { 280 if (!IPC_GET_RETVAL(answer->data)) { 280 if (!IPC_GET_RETVAL(answer->data)) { 281 281 irq_spinlock_lock(&answer->sender->lock, true); 282 282 as_t *as = answer->sender->as; -
kernel/generic/src/lib/rd.c
r3b71e84d r7aaed09 33 33 /** 34 34 * @file 35 * @brief 35 * @brief RAM disk support. 36 36 * 37 37 * Support for RAM disk images. … … 39 39 40 40 #include <lib/rd.h> 41 #include <byteorder.h>42 41 #include <mm/frame.h> 43 42 #include <sysinfo/sysinfo.h> 44 43 #include <ddi/ddi.h> 45 #include <align.h>46 44 47 static parea_t rd_parea; /**< Physical memory area for rd. */ 45 /** Physical memory area for RAM disk. */ 46 static parea_t rd_parea; 48 47 49 /** 50 * RAM disk initialization routine. At this point, the RAM disk memory is shared 51 * and information about the share is provided as sysinfo values to the 52 * userspace tasks. 53 */ 54 int init_rd(rd_header_t *header, size_t size) 48 /** RAM disk initialization routine 49 * 50 * The information about the RAM disk is provided as sysinfo 51 * values to the uspace tasks. 52 * 53 */ 54 void init_rd(void *data, size_t size) 55 55 { 56 /* Identify RAM disk */ 57 if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) || 58 (header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3)) 59 return RE_INVALID; 56 uintptr_t base = KA2PA((uintptr_t) data); 57 ASSERT((base % FRAME_SIZE) == 0); 60 58 61 /* Identify version */ 62 if (header->version != RD_VERSION) 63 return RE_UNSUPPORTED; 64 65 uint32_t hsize; 66 uint64_t dsize; 67 switch (header->data_type) { 68 case RD_DATA_LSB: 69 hsize = uint32_t_le2host(header->header_size); 70 dsize = uint64_t_le2host(header->data_size); 71 break; 72 case RD_DATA_MSB: 73 hsize = uint32_t_be2host(header->header_size); 74 dsize = uint64_t_be2host(header->data_size); 75 break; 76 default: 77 return RE_UNSUPPORTED; 78 } 79 80 if ((hsize % FRAME_SIZE) || (dsize % FRAME_SIZE)) 81 return RE_UNSUPPORTED; 82 83 if (hsize > size) 84 return RE_INVALID; 85 86 if ((uint64_t) hsize + dsize > size) 87 dsize = size - hsize; 88 89 rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), 90 FRAME_SIZE); 91 rd_parea.frames = SIZE2FRAMES(dsize); 59 rd_parea.pbase = base; 60 rd_parea.frames = SIZE2FRAMES(size); 92 61 rd_parea.unpriv = false; 93 62 rd_parea.mapped = false; 94 63 ddi_parea_register(&rd_parea); 95 64 96 65 sysinfo_set_item_val("rd", NULL, true); 97 sysinfo_set_item_val("rd.header_size", NULL, hsize); 98 sysinfo_set_item_val("rd.size", NULL, dsize); 99 sysinfo_set_item_val("rd.address.physical", NULL, 100 (sysarg_t) KA2PA((void *) header + hsize)); 101 102 return RE_OK; 66 sysinfo_set_item_val("rd.size", NULL, size); 67 sysinfo_set_item_val("rd.address.physical", NULL, (sysarg_t) base); 103 68 } 104 69 -
kernel/generic/src/main/kinit.c
r3b71e84d r7aaed09 179 179 for (i = 0; i < init.cnt; i++) { 180 180 if (init.tasks[i].addr % FRAME_SIZE) { 181 printf("init[%zu] .addris not frame aligned\n", i);181 printf("init[%zu]: Address is not frame aligned\n", i); 182 182 programs[i].task = NULL; 183 183 continue; … … 203 203 namebuf, &programs[i]); 204 204 205 if ((rc == 0) && (programs[i].task != NULL)) { 205 if (rc == 0) { 206 if (programs[i].task != NULL) { 207 /* 208 * Set capabilities to init userspace tasks. 209 */ 210 cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER | 211 CAP_IO_MANAGER | CAP_IRQ_REG); 212 213 if (!ipc_phone_0) 214 ipc_phone_0 = &programs[i].task->answerbox; 215 } 216 206 217 /* 207 * Set capabilities to init userspace tasks. 218 * If programs[i].task == NULL then it is 219 * the program loader and it was registered 220 * successfully. 208 221 */ 209 cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER | 210 CAP_IO_MANAGER | CAP_IRQ_REG); 211 212 if (!ipc_phone_0) 213 ipc_phone_0 = &programs[i].task->answerbox; 214 } else if (rc == 0) { 215 /* It was the program loader and was registered */ 216 } else { 217 /* RAM disk image */ 218 int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size); 219 220 if (rd != RE_OK) 221 printf("Init binary %zu not used (error %d)\n", i, rd); 222 } 222 } else if (i == init.cnt - 1) { 223 /* 224 * Assume the last task is the RAM disk. 225 */ 226 init_rd((void *) init.tasks[i].addr, init.tasks[i].size); 227 } else 228 printf("init[%zu]: Init binary load failed (error %d)\n", i, rc); 223 229 } 224 230 -
kernel/generic/src/main/main.c
r3b71e84d r7aaed09 268 268 * Create the first thread. 269 269 */ 270 thread_t *kinit_thread 271 =thread_create(kinit, NULL, kernel, 0, "kinit", true);270 thread_t *kinit_thread = 271 thread_create(kinit, NULL, kernel, 0, "kinit", true); 272 272 if (!kinit_thread) 273 273 panic("Cannot create kinit thread."); -
kernel/generic/src/mm/page.c
r3b71e84d r7aaed09 53 53 * We assume that the other processors are either not using the mapping yet 54 54 * (i.e. during the bootstrap) or are executing the TLB shootdown code. While 55 * we don't care much about the former case, the processors in the latter case 55 * we don't care much about the former case, the processors in the latter case 56 56 * will do an implicit serialization by virtue of running the TLB shootdown 57 57 * interrupt handler. … … 198 198 } 199 199 200 int page_find_mapping(uintptr_t virt, void **phys) 201 { 202 mutex_lock(&AS->lock); 203 204 pte_t *pte = page_mapping_find(AS, virt, false); 205 if ((!PTE_VALID(pte)) || (!PTE_PRESENT(pte))) { 206 mutex_unlock(&AS->lock); 207 return ENOENT; 208 } 209 210 *phys = (void *) PTE_GET_FRAME(pte) + 211 (virt - ALIGN_DOWN(virt, PAGE_SIZE)); 212 213 mutex_unlock(&AS->lock); 214 215 return EOK; 216 } 200 217 201 218 /** Syscall wrapper for getting mapping of a virtual page. 202 * 203 * @retval EOK Everything went find, @p uspace_frame and @p uspace_node 204 * contains correct values. 205 * @retval ENOENT Virtual address has no mapping. 206 */ 207 sysarg_t sys_page_find_mapping(uintptr_t virt_address, 208 uintptr_t *uspace_frame) 209 { 210 mutex_lock(&AS->lock); 211 212 pte_t *pte = page_mapping_find(AS, virt_address, false); 213 if (!PTE_VALID(pte) || !PTE_PRESENT(pte)) { 214 mutex_unlock(&AS->lock); 215 216 return (sysarg_t) ENOENT; 217 } 218 219 uintptr_t phys_address = PTE_GET_FRAME(pte); 220 221 mutex_unlock(&AS->lock); 222 223 int rc = copy_to_uspace(uspace_frame, 224 &phys_address, sizeof(phys_address)); 225 if (rc != EOK) { 226 return (sysarg_t) rc; 227 } 228 229 return EOK; 219 * 220 * @return EOK on success. 221 * @return ENOENT if no virtual address mapping found. 222 * 223 */ 224 sysarg_t sys_page_find_mapping(uintptr_t virt, void *phys_ptr) 225 { 226 void *phys; 227 int rc = page_find_mapping(virt, &phys); 228 if (rc != EOK) 229 return rc; 230 231 rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys)); 232 return (sysarg_t) rc; 230 233 } 231 234 -
kernel/generic/src/syscall/syscall.c
r3b71e84d r7aaed09 176 176 (syshandler_t) sys_device_assign_devno, 177 177 (syshandler_t) sys_physmem_map, 178 (syshandler_t) sys_dmamem_map, 179 (syshandler_t) sys_dmamem_unmap, 178 180 (syshandler_t) sys_iospace_enable, 179 181 (syshandler_t) sys_register_irq,
Note:
See TracChangeset
for help on using the changeset viewer.