Changeset 27
- Timestamp:
- 02/05/06 15:42:13 (6 years ago)
- Files:
-
- arch/i386/kernel/callgate.c (modified) (12 diffs)
- arch/i386/kernel/irq.c (modified) (1 diff)
- drivers/char/misc.c (modified) (1 diff)
- fs/file_table.c (modified) (2 diffs)
- fs/ioctl.c (modified) (2 diffs)
- fs/open.c (modified) (1 diff)
- fs/proc/generic.c (modified) (1 diff)
- fs/read_write.c (modified) (10 diffs)
- include/asm-i386/callgate.h (modified) (1 diff)
- include/linux/sched.h (modified) (1 diff)
- kernel/module.c (modified) (2 diffs)
- kernel/timer.c (modified) (1 diff)
- .version (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
arch/i386/kernel/callgate.c
r26 r27 66 66 "popl %ds\n\t" 67 67 68 #define PAGE_OF(addr) ((addr) & PAGE_MASK) 69 68 70 //#define NO_PARAMS 69 71 void *ring1_driver_helper; … … 106 108 void do_benchmark(unsigned long hi, unsigned long lo); 107 109 void lcall_nop(void); 110 unsigned long map_pages(void *virt_addr, unsigned long count, int ring, void **origmem); 111 112 struct driver_usage { 113 void *driver_id; 114 struct driver_usage *next; 115 }; 116 117 struct ring_page_map { 118 unsigned long pa; //Physical address of page (page aligned) 119 int num_pages; //Number of consecutive pages in this mapping 120 unsigned long vaddr; //Virtual address of page in driver space 121 void *origaddr; //Virtual address for vunmap 122 struct driver_usage *refs; //Head of linked list of drivers using this mapping 123 struct ring_page_map *next; //Next mapping 124 }; 125 126 struct ring_page_map *ring1_head; 127 struct ring_page_map *ring2_head; 128 129 108 130 struct task_struct *mod_get_current(void) { 109 131 struct task_struct *tsk=current; … … 113 135 if (!tsk->ring) 114 136 return current; 115 tsk->currentaddr=(struct task_struct*) map_struct(tsk, sizeof(*tsk) +PAGE_SIZE, tsk->ring, &tsk->origcurrentaddr);137 tsk->currentaddr=(struct task_struct*) map_struct(tsk, sizeof(*tsk), tsk->ring, 1, tsk->driver_id); 116 138 tsk->currentmapped=1; 117 139 return tsk->currentaddr; … … 330 352 create_callgate((unsigned long) callgate_entry15, 2, 15); 331 353 create_callgate((unsigned long) lcall_nop, 2, 0); 354 355 ring1_head=ring2_head=NULL; 332 356 } 333 357 334 358 //Cannot call from no context (ie interrupt handler) 335 int calldriver(unsigned long addr, unsigned long *argv, int argc, struct mm_struct *mm, unsigned long ptrbitmap)359 int calldriver(unsigned long addr, void **argv, unsigned int *sizes, int argc, struct mm_struct *mm, unsigned long ptrbitmap, unsigned long flags) 336 360 { 337 361 struct task_struct *tsk; … … 341 365 int i; 342 366 void * origmems[argc]; 343 if (in_interrupt() && !( ptrbitmap& NO_WAIT))367 if (in_interrupt() && !(flags & NO_WAIT)) 344 368 { 345 369 printk(KERN_ERR "Cannot call driver code from interrupt handler\n"); … … 358 382 return tsk->exit_code;*/ 359 383 360 tsk=find_worker_thread(addr, ptrbitmap& USE_RESERVED);384 tsk=find_worker_thread(addr, flags & USE_RESERVED); 361 385 if (!tsk) { 362 386 printk(KERN_ERR "Could not find worker thread for address %x\n", addr); … … 405 429 if (ptrbitmap & (1 << (argc))) { 406 430 //this is a ptr, so map it in 407 //FIXME: Assuming all struct are less than 512B 408 addrs[argc]=map_struct((void*) argv[argc], 512, tsk->ring, &origmems[argc]); 431 addrs[argc]=map_struct((unsigned long) argv[argc], sizes[argc], tsk->ring, 0, NULL); 409 432 // addrs[argc]=0; 410 433 *(unsigned long*)(regs->esp)=addrs[argc]; 411 434 } else { 412 435 addrs[argc]=0; 413 *(unsigned long*)(regs->esp)= argv[argc];436 *(unsigned long*)(regs->esp)=(unsigned long) argv[argc]; 414 437 } 415 438 } … … 417 440 #endif 418 441 wake_up_process(tsk); 419 if (!( ptrbitmap& NO_WAIT)) {442 if (!(flags & NO_WAIT)) { 420 443 tsk->bytes_to_pop=0; 421 444 sleep_on(&tsk->wait_driverfinish); … … 426 449 // ClearPageReserved(pfn_to_page(__pa(argv[i]) >> PAGE_SHIFT)); 427 450 // ClearPageReserved(pfn_to_page((__pa(argv[i]) >> PAGE_SHIFT) + 1)); 428 vunmap(origmems[i]);451 //vunmap(origmems[i]); 429 452 } 430 453 regs->esp+=4; … … 438 461 } 439 462 440 unsigned long map_struct(void *kernel_struct, unsigned long size, int ring, void **origmem) 463 unsigned long map_struct(unsigned long kernel_struct, unsigned long size, int ring, int update_ref, void *driver_id) 464 { 465 struct ring_page_map *ptr=NULL; 466 if (ring==1) ptr=ring1_head; 467 else if (ring==2) ptr=ring2_head; 468 else BUG(); 469 470 while (ptr) { 471 if (__pa(PAGE_OF(kernel_struct)) == ptr->pa) { 472 //Check if size is too big 473 if (PAGE_OF(kernel_struct+size)!=PAGE_OF(kernel_struct) && ptr->num_pages==1) 474 continue; 475 if (update_ref) { 476 struct driver_usage *dptr=ptr->refs; 477 while (dptr) { 478 if (dptr->driver_id == driver_id) 479 break; 480 dptr=dptr->next; 481 } 482 if (!dptr) { 483 struct driver_usage *newuse; 484 newuse=(struct driver_usage*) kmalloc(sizeof(struct driver_usage), GFP_KERNEL); 485 newuse->driver_id=driver_id; 486 newuse->next=ptr->refs; 487 ptr->refs=newuse; 488 } 489 } 490 return (ptr->vaddr + (kernel_struct - PAGE_OF(kernel_struct))); 491 } 492 ptr=ptr->next; 493 } 494 //Not found 495 ptr=(struct ring_page_map*) kmalloc(sizeof(struct ring_page_map), GFP_KERNEL); 496 ptr->pa=__pa(PAGE_OF(kernel_struct)); 497 ptr->num_pages=1 + (PAGE_OF(kernel_struct)!=PAGE_OF(kernel_struct+size)); 498 ptr->vaddr=map_pages((void*) PAGE_OF(kernel_struct), ptr->num_pages, ring, &ptr->origaddr); 499 ptr->refs=NULL; 500 if (update_ref) { 501 struct driver_usage *dptr=ptr->refs; 502 while (dptr) { 503 if (dptr->driver_id == driver_id) 504 break; 505 dptr=dptr->next; 506 } 507 if (!dptr) { 508 struct driver_usage *newuse; 509 newuse=(struct driver_usage*) kmalloc(sizeof(struct driver_usage), GFP_KERNEL); 510 newuse->driver_id=driver_id; 511 newuse->next=ptr->refs; 512 ptr->refs=newuse; 513 } 514 } 515 if (ring==1) { 516 ptr->next=ring1_head; 517 ring1_head=ptr; 518 } else if (ring==2) { 519 ptr->next=ring2_head; 520 ring2_head=ptr; 521 } 522 return (ptr->vaddr + (kernel_struct - PAGE_OF(kernel_struct))); 523 524 } 525 526 //Hey, look, it's a function comment 527 //virt_addr: kernel space virtual address of page (should be page aligned) 528 //count: number of pages to map (1 or 2) 529 //ring: ring to map into 530 //origmem: place to return starting address we got from __vmalloc for vunmap later 531 //returns address in the driver address space 532 unsigned long map_pages(void *virt_addr, unsigned long count, int ring, void **origmem) 441 533 { 442 534 struct vm_area_struct *vma; 443 535 unsigned long addr=0; 444 536 int res1, res2; 445 if (! kernel_struct || !size)537 if (!virt_addr || !count || count > 2) 446 538 return -EINVAL; 447 539 vma=(struct vm_area_struct*) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL); 448 540 down_write(&init_mm.mmap_sem); 449 541 542 //Is the +1 needed? I'm not sure... 450 543 if (ring == 1) 451 addr=(unsigned long) __vmalloc(PAGE_SIZE + size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1| VMALLOC_NOMAP);544 addr=(unsigned long) __vmalloc(PAGE_SIZE * (count+1), GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1| VMALLOC_NOMAP); 452 545 else if (ring == 2) 453 addr=(unsigned long) __vmalloc(PAGE_SIZE + size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2 | VMALLOC_NOMAP);546 addr=(unsigned long) __vmalloc(PAGE_SIZE * (count+1), GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2 | VMALLOC_NOMAP); 454 547 else 455 548 BUG(); … … 459 552 460 553 vma->vm_mm=&init_mm; 461 res1=PageReserved(pfn_to_page(__pa( kernel_struct) >> PAGE_SHIFT));462 res2=PageReserved(pfn_to_page(__pa( kernel_struct) >> PAGE_SHIFT)+1);554 res1=PageReserved(pfn_to_page(__pa(virt_addr) >> PAGE_SHIFT)); 555 res2=PageReserved(pfn_to_page(__pa(virt_addr) >> PAGE_SHIFT)+1); 463 556 if (!res1) 464 SetPageReserved(pfn_to_page(__pa( kernel_struct) >> PAGE_SHIFT));557 SetPageReserved(pfn_to_page(__pa(virt_addr) >> PAGE_SHIFT)); 465 558 if (!res2) 466 SetPageReserved(pfn_to_page((__pa( kernel_struct) >> PAGE_SHIFT) + 1));467 remap_page_range(vma, addr, __pa( kernel_struct), size, PAGE_KERNEL);559 SetPageReserved(pfn_to_page((__pa(virt_addr) >> PAGE_SHIFT) + 1)); 560 remap_page_range(vma, addr, __pa(virt_addr), PAGE_SIZE * count, PAGE_KERNEL); 468 561 if (!res1) 469 ClearPageReserved(pfn_to_page(__pa( kernel_struct) >> PAGE_SHIFT));562 ClearPageReserved(pfn_to_page(__pa(virt_addr) >> PAGE_SHIFT)); 470 563 if (!res2) 471 ClearPageReserved(pfn_to_page((__pa(kernel_struct) >> PAGE_SHIFT) + 1)); 472 addr+=(unsigned long) kernel_struct & (PAGE_SIZE -1); 564 ClearPageReserved(pfn_to_page((__pa(virt_addr) >> PAGE_SHIFT) + 1)); 473 565 474 566 out: up_write(&init_mm.mmap_sem); … … 476 568 return addr; 477 569 } 478 479 570 480 571 arch/i386/kernel/irq.c
r22 r27 233 233 retval |= action->handler(irq, action->dev_id, regs); 234 234 else { 235 unsigned long args[3]={irq, (unsigned long) action->dev_id, (unsigned long) regs}; 236 calldriver((unsigned long) action->handler, args, 3, NULL, NO_WAIT | 0);235 CALLDRIVER_PREP3(my, irq, action->dev_id, regs) 236 calldriver((unsigned long) action->handler, my_args, my_sizes, 3, NULL, 0, NO_WAIT); 237 237 retval|=IRQ_HANDLED; 238 238 } drivers/char/misc.c
r21 r27 173 173 err=file->f_op->open(inode,file); 174 174 else { 175 args[0]=(unsigned long) inode; 176 args[1]=(unsigned long) file; 177 err=calldriver((unsigned long) file->f_op->open, args, 2, current->mm, 3); 175 CALLDRIVER_PREP2(open, inode, file) 176 err=calldriver((unsigned long) file->f_op->open, open_args, open_sizes, 2, current->mm, 3, 0); 178 177 } 179 178 fs/file_table.c
r21 r27 151 151 file->f_op->release(inode, file); 152 152 else { 153 unsigned long args[2]={(unsigned long) inode, (unsigned long) file}; 154 calldriver((unsigned long) file->f_op->release, args, 2, current->mm, 3);153 CALLDRIVER_PREP2(rel, inode, file) 154 calldriver((unsigned long) file->f_op->release, rel_args, rel_sizes, 2, current->mm, 3, 0); 155 155 } 156 156 } … … 188 188 file->f_op->release(inode, file); 189 189 else { 190 unsigned long args[2]={(unsigned long) inode, (unsigned long) file}; 191 calldriver((unsigned long) file->f_op->release, args, 2, current->mm, 3);190 CALLDRIVER_PREP2(rel, inode, file) 191 calldriver((unsigned long) file->f_op->release, rel_args, rel_sizes, 2, current->mm, 3, 0); 192 192 } 193 193 } fs/ioctl.c
r21 r27 49 49 return filp->f_op->ioctl(inode, filp, cmd, arg); 50 50 else { 51 unsigned long args[4]; 52 args[0]=(unsigned long) inode; 53 args[1]=(unsigned long) filp; 54 args[2]=(unsigned long) cmd; 55 args[3]=(unsigned long) arg; 56 return calldriver((unsigned long) filp->f_op->ioctl, args, 4, current->mm, 3); 51 CALLDRIVER_PREP4(ioctl, inode, filp, cmd, arg) 52 return calldriver((unsigned long) filp->f_op->ioctl, ioctl_args, ioctl_sizes, 4, current->mm, 3, 0); 57 53 } 58 54 } … … 140 136 error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); 141 137 else { 142 unsigned long args[4]; 143 args[0]=(unsigned long) filp->f_dentry->d_inode; 144 args[1]=(unsigned long) filp; 145 args[2]=(unsigned long) cmd; 146 args[3]=(unsigned long) arg; 147 error=calldriver((unsigned long) filp->f_op->ioctl, args, 4, current->mm, 3); 138 CALLDRIVER_PREP4(ioctl, filp->f_dentry->d_inode, filp, cmd, arg) 139 error=calldriver((unsigned long) filp->f_op->ioctl, ioctl_args, ioctl_sizes, 4, current->mm, 3, 0); 148 140 } 149 141 } fs/open.c
r14 r27 802 802 error = f->f_op->open(inode,f); 803 803 else { 804 args[0]=(unsigned long) inode; 805 args[1]=(unsigned long) f; 806 error = calldriver((unsigned long) f->f_op->open, args, 2, current->mm, 3); 804 CALLDRIVER_PREP2(open, inode, f) 805 error = calldriver((unsigned long) f->f_op->open, open_args, open_sizes, 2, current->mm, 3, 0); 807 806 } 808 807 if (error) fs/proc/generic.c
r21 r27 121 121 count, &eof, dp->data); 122 122 } else { 123 unsigned long args[6]={(unsigned long) page, (unsigned long) &start, (unsigned long) *ppos, (unsigned long) count, (unsigned long) &eof, (unsigned long) dp->data}; 124 n=calldriver((unsigned long) dp->read_proc, args, 6, current->mm, 19);123 CALLDRIVER_PREP6(proc, page, &start, (unsigned long) *ppos, count, &eof, dp->data) 124 n=calldriver((unsigned long) dp->read_proc, proc_args, proc_sizes, 6, current->mm, 19, 0); 125 125 } 126 126 } else fs/read_write.c
r21 r27 187 187 struct kiocb kiocb; 188 188 ssize_t ret; 189 unsigned long args[4];190 189 191 190 init_sync_kiocb(&kiocb, filp); … … 194 193 ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos); 195 194 else { 196 args[0]=(unsigned long) &kiocb;197 args[1]=(unsigned long) buf;198 args[2]=(unsigned long) len;199 args[3]=(unsigned long) kiocb.ki_pos;200 ret = calldriver((unsigned long) filp->f_op->aio_read, a rgs, 4, current->mm, 0);195 //Well, the last parameter is actually 64-bits 196 //We could deal with this, it would require extra work though 197 //Let's just assume no one will ever call this function 198 CALLDRIVER_PREP4(aio, &kiocb, buf, len, (unsigned long) kiocb.ki_pos) 199 ret = calldriver((unsigned long) filp->f_op->aio_read, aio_args,aio_sizes, 4, current->mm, 1, 0); 201 200 } 202 201 … … 213 212 struct inode *inode = file->f_dentry->d_inode; 214 213 ssize_t ret; 215 unsigned long args[4];216 214 217 215 if (!(file->f_mode & FMODE_READ)) … … 228 226 ret = file->f_op->read(file, buf, count, pos); 229 227 else { 230 args[0]=(unsigned long) file; 231 args[1]=(unsigned long) buf; 232 args[2]=(unsigned long) count; 233 args[3]=(unsigned long) pos; 234 ret = calldriver((unsigned long) file->f_op->read, args, 4, current->mm, 9); 228 CALLDRIVER_PREP4(read, file, buf, count, pos) 229 ret = calldriver((unsigned long) file->f_op->read, read_args, read_sizes, 4, current->mm, 9, 0); 235 230 } 236 231 } … … 251 246 struct kiocb kiocb; 252 247 ssize_t ret; 253 unsigned long args[4];254 248 255 249 init_sync_kiocb(&kiocb, filp); … … 258 252 ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos); 259 253 else { 260 args[0]=(unsigned long) &kiocb; 261 args[1]=(unsigned long) buf; 262 args[2]=(unsigned long) len; 263 args[3]=(unsigned long) kiocb.ki_pos; 264 ret = calldriver((unsigned long) filp->f_op->aio_write, args, 4, current->mm, 0); 254 //See commend about aio_read 255 CALLDRIVER_PREP4(aio, &kiocb, buf, len, (unsigned long) kiocb.ki_pos) 256 ret = calldriver((unsigned long) filp->f_op->aio_write, aio_args, aio_sizes, 4, current->mm, 1, 0); 265 257 } 266 258 … … 278 270 struct inode *inode = file->f_dentry->d_inode; 279 271 ssize_t ret; 280 unsigned long args[4];281 272 282 273 if (!(file->f_mode & FMODE_WRITE)) … … 293 284 ret = file->f_op->write(file, buf, count, pos); 294 285 else { 295 args[0]=(unsigned long) file; 296 args[1]=(unsigned long) buf; 297 args[2]=(unsigned long) count; 298 args[3]=(unsigned long) pos; 299 ret = calldriver((unsigned long) file->f_op->write, args, 4, current->mm, 9); 286 CALLDRIVER_PREP4(write, file, buf, count, pos) 287 ret = calldriver((unsigned long) file->f_op->write, write_args, write_sizes, 4, current->mm, 9, 0); 300 288 } 301 289 } … … 589 577 ssize_t retval; 590 578 int fput_needed_in, fput_needed_out; 591 unsigned long args[5];592 579 593 580 /* … … 654 641 retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); 655 642 else { 656 args[0]=(unsigned long) in_file; 657 args[1]=(unsigned long) ppos; 658 args[2]=(unsigned long) count; 659 args[3]=(unsigned long) file_send_actor; 660 args[4]=(unsigned long) out_file; 661 retval = calldriver((unsigned long) in_file->f_op->sendfile, args, 5, current->mm, 0); 643 CALLDRIVER_PREP5(send, in_file, ppos, count, file_send_actor, out_file) 644 retval = calldriver((unsigned long) in_file->f_op->sendfile, send_args, send_sizes, 5, current->mm, 0x19, 0); 662 645 } 663 646 include/asm-i386/callgate.h
r21 r27 23 23 struct mm_struct; 24 24 struct task_struct; 25 extern int calldriver(unsigned long addr, unsigned long *argv, int argc, struct mm_struct *mm, unsigned long ptrbitmap); 26 extern unsigned long map_struct(void *kernel_struct, unsigned long size, int ring, void **origmem); 25 extern int calldriver(unsigned long addr, void **argv, unsigned int *sizes, int argc, struct mm_struct *mm, unsigned long ptrbitmap, unsigned long flags); 26 27 extern unsigned long map_struct(unsigned long kernel_struct, unsigned long size, int ring, int update_ref, void *driver_id); 28 //Macros for helping create structures for calldriver 29 #define CALLDRIVER_PREP2(name, param1, param2) \ 30 void *name ## _args[2]={ (void*) param1, (void*) param2};\ 31 unsigned int name ## _sizes[2]={sizeof(param1), sizeof(param2)}; 32 #define CALLDRIVER_PREP3(name, param1, param2, param3) \ 33 void *name ## _args[3]={(void*)param1, (void*) param2, (void*) param3};\ 34 unsigned int name ## _sizes[3]={sizeof(param1), sizeof(param2), sizeof(param3)}; 35 #define CALLDRIVER_PREP4(name, param1, param2, param3, param4) \ 36 void *name ## _args[4]={(void*) param1, (void*) param2, (void*) param3, (void*) param4};\ 37 unsigned int name ## _sizes[4]={sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4)}; 38 #define CALLDRIVER_PREP5(name, param1, param2, param3, param4, param5) \ 39 void *name ## _args[5]={(void*) param1, (void*) param2, (void*) param3, (void*) param4, (void*) param5};\ 40 unsigned int name ## _sizes[5]={sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5)}; 41 #define CALLDRIVER_PREP6(name, param1, param2, param3, param4, param5, param6) \ 42 void *name ## _args[6]={(void*) param1, (void*) param2, (void*) param3, (void*) param4, (void*) param5, (void*) param6};\ 43 unsigned int name ## _sizes[6]={sizeof(param1), sizeof(param2), sizeof(param3), sizeof(param4), sizeof(param5), sizeof(param6)}; 44 27 45 28 46 //FLAGS for calldriver 29 #define NO_WAIT 0x 8000000030 #define USE_RESERVED 0x 4000000047 #define NO_WAIT 0x00000001 48 #define USE_RESERVED 0x00000002 31 49 #endif include/linux/sched.h
r22 r27 527 527 int bytes_to_pop; 528 528 struct task_struct *caller; 529 void *driver_id; 529 530 }; 530 531 kernel/module.c
r24 r27 630 630 if (mod->ring) { 631 631 if (mod->exit) 632 calldriver((unsigned long) mod->exit, NULL, 0, NULL, USE_RESERVED);632 calldriver((unsigned long) mod->exit, NULL, NULL, 0, NULL, 0, USE_RESERVED); 633 633 down(&module_mutex); 634 634 //NEW: get rid of threads … … 1912 1912 } 1913 1913 mod->worker_threads[i]->ring=mod->ring; 1914 mod->worker_threads[i]->driver_id=mod; 1914 1915 } 1915 1916 schedule(); 1916 1917 printk("mod pointer is %x, per cpu is %d\n", mod, mod->percpu); 1917 1918 printk("Invoking init method...\n"); 1918 ret=calldriver((unsigned long) mod->init, NULL, 0, NULL, 0);1919 ret=calldriver((unsigned long) mod->init, NULL, NULL, 0, NULL, 0, 0); 1919 1920 } else { 1920 1921 ret=mod->init(); kernel/timer.c
r22 r27 458 458 fn(data); 459 459 else { 460 461 calldriver((unsigned long)fn, &data, 1, NULL, NO_WAIT); 460 unsigned int len=sizeof(data); 461 void *arg=&data; 462 calldriver((unsigned long)fn, &arg, &len, 1, NULL, 0, NO_WAIT); 462 463 } 463 464 spin_lock_irq(&base->lock); .version
r26 r27 1 299 1 301
