Changeset 8

Show
Ignore:
Timestamp:
10/15/05 18:00:42 (6 years ago)
Author:
dkaplan1
Message:

Added worker thread per driver. Thread sleeps until it is needed

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • arch/i386/kernel/callgate.c

    r7 r8  
    5353void *ring2_driver_helper; 
    5454 
    55  
    5655void callgate_entry1(int oldcs, unsigned long param1); 
    5756void callgate_entry2(int oldcs, unsigned long param1, unsigned long param2); 
     
    7675        "pushl 16(%ebp)\n\t" 
    7776        "decl %ecx\n\t" 
    78         "cmpl $2, %ecx\n\t" 
     77        "cmpl $3, %ecx\n\t" 
    7978        "ja done2\n\t" 
    8079        "call *callgate_table2(,%ecx,4)\n\t" 
     
    8382        "leave\n\t" 
    8483        "lret $8\n\t" 
    85         "callgate_table2: .long driver_printdiag, do_exit
     84        "callgate_table2: .long driver_printdiag, do_exit, driver_exit
    8685); 
    8786 
     
    161160        "pushl %edx\n\t" 
    162161        "call *%ebx\n\t" 
    163         "pushl %eax\n\t" 
    164         "pushl $2\n\t" 
    165         "lcall $0x108, $0\n\t" 
     162        "movl %eax, %ebx\n\t" 
     163        "movl $285, %eax\n\t" 
     164        "int $0x80\n\t" 
     165        //"pushl %eax\n\t" 
     166       // "pushl $3\n\t" 
     167      //  "lcall $0x108, $0\n\t" 
    166168        "end_of_driver_thread_helper:\n\t" 
    167169        "ud2\n" 
     
    181183} 
    182184 
     185//Cannot call from no context (ie interrupt handler) 
     186int calldriver(unsigned long addr, void *data, struct mm_struct *mm, unsigned long flags) 
     187{ 
     188    struct task_struct *tsk; 
     189    struct pt_regs *regs; 
     190    if (in_interrupt()) 
     191    { 
     192        printk(KERN_ERR "Cannot call driver code from interrupt handler\n"); 
     193        return -1; 
     194    } 
     195/* 
     196    //try to find the stack! 
     197    stack=find_module_stack(addr); 
     198    if (!stack) { 
     199        printk(KERN_ERR "Could not find stack for code at address %x\n", (unsigned int) addr); 
     200        return -1; 
     201    } 
     202    pid=driver_thread(addr, data, stack, 0, ring); 
     203    tsk=find_task_by_pid(pid); 
     204    interruptible_sleep_on(&tsk->wait_kernexit); 
     205    return tsk->exit_code;*/ 
     206 
     207    tsk=find_worker_thread(addr); 
     208    if (!tsk) { 
     209        printk(KERN_ERR "Could not find worker thread for address %x\n", addr); 
     210        return -1; 
     211    } 
     212    if (!tsk->available) { 
     213        printk(KERN_ERR "Thread busy...increase size of driver thread pool\n"); 
     214        return -1; 
     215    } 
     216    tsk->available=0; 
     217    //Set memory map 
     218    if (mm) 
     219        tsk->mm=mm; 
     220 
     221    //Set new state for thread 
     222    //show_stack(tsk, NULL); 
     223    regs=task_pt_regs(tsk); 
     224    //show_regs(regs); 
     225    regs->ebx=addr; 
     226    regs->edx=(unsigned long) data; 
     227    if (tsk->ring == 1) { 
     228            regs->eip=(unsigned long) ring1_driver_helper; 
     229    } else if (tsk->ring == 2) { 
     230            regs->eip=(unsigned long) ring2_driver_helper; 
     231    }  
     232    else 
     233        BUG(); 
     234     
     235    //printk("Going...\n"); 
     236    //show_regs(regs); 
     237    wake_up_process(tsk);     
     238 
     239    interruptible_sleep_on(&tsk->wait_driverfinish); 
     240    return tsk->exit_code; 
     241} 
     242 
     243     
     244         
     245     
     246 
     247 
  • arch/i386/kernel/entry.S

    r6 r8  
    913913        .long sys_ni_syscall            /* reserved for kexec */ 
    914914        .long sys_printdiag 
     915        .long driver_exit /* 285*/ 
    915916 
    916917syscall_table_size=(.-sys_call_table) 
  • arch/i386/kernel/process.c

    r7 r8  
    346346} 
    347347*/ 
    348 int driver_thread(unsigned long fn, void * arg, unsigned long flags, int ring) 
     348int create_driver_thread(unsigned long flags, int ring) 
    349349{ 
    350350        struct pt_regs regs; 
    351   unsigned char *stack_start=NULL; 
     351  void *stack_start=NULL; 
     352  void *orig_stack=NULL; 
     353  int pid; 
    352354        memset(&regs, 0, sizeof(regs)); 
    353       regs.ebx = (unsigned long) fn; 
    354       regs.edx = (unsigned long) arg; 
     355//    regs.ebx = (unsigned long) fn; 
     356//    regs.edx = (unsigned long) arg; 
    355357 
    356358  if (!ring1_driver_helper) 
     
    362364      regs.xcs = __RING1_CS; 
    363365      regs.xss = __RING1_DS; 
    364       regs.eip = (unsigned long) ring1_driver_helper; 
    365       stack_start=(unsigned char*) __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1); 
     366  //    regs.eip = (unsigned long) ring1_driver_helper; 
     367      orig_stack= __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1); 
    366368  //    printk("Created ring 1 stack at %x", stack_start); 
    367369  } 
     
    373375      regs.xss = __RING2_DS; 
    374376      regs.eip = (unsigned long) ring2_driver_helper; 
    375       stack_start=(unsigned char*) __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2); 
     377      orig_stack= __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2); 
    376378    //  printk("Created ring 2 stack at %x", stack_start); 
    377379  } 
    378380  else 
    379381      BUG(); 
    380   stack_start+=8152; //leave 40 bytes empty 
     382  stack_start=(unsigned char*) orig_stack + 8152; //leave 40 bytes empty 
    381383        regs.orig_eax = -1; 
    382384   
    383385        regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; 
    384  
    385386        /* Ok, create the new process.. */ 
    386387  //printk("Calling do_fork"); 
    387         return do_fork(flags | CLONE_VM | CLONE_UNTRACED, (unsigned long) stack_start, &regs, 0, NULL, NULL); 
     388        pid=do_fork(flags | CLONE_STOPPED | CLONE_VM | CLONE_UNTRACED, (unsigned long) stack_start, &regs, 0, NULL, NULL); 
     389  find_task_by_pid(pid)->orig_stack=orig_stack; 
     390  find_task_by_pid(pid)->available=1; 
     391  return pid; 
    388392} 
    389393/* 
  • arch/i386/kernel/traps.c

    r6 r8  
    9494asmlinkage void machine_check(void); 
    9595 
    96 static int kstack_depth_to_print = 24; 
     96//NOTE: changed 
     97static int kstack_depth_to_print = 48; 
    9798 
    9899static int valid_stack_ptr(struct task_struct *task, void *p) 
  • include/asm-i386/processor.h

    r6 r8  
    492492 
    493493/*Create driver thread in other ring*/ 
    494 extern int driver_thread(unsigned long fn, void * arg, unsigned long flags, int ring); 
     494extern int create_driver_thread(unsigned long flags, int ring); 
     495 
    495496 
    496497extern unsigned long thread_saved_pc(struct task_struct *tsk); 
  • include/linux/module.h

    r1 r8  
    4848extern int init_module(void); 
    4949extern void cleanup_module(void); 
     50 
     51extern struct task_struct *find_worker_thread(unsigned long addr); 
    5052 
    5153/* Archs provide a method of finding the correct exception table. */ 
     
    308310        /* Fake kernel param for refcnt. */ 
    309311        struct kernel_param refcnt_param; 
     312 
     313  /* Locatoin of stack in lower ring*/ 
     314  //void *stack_start; 
     315 
     316  /*task struct of worker thread*/ 
     317  struct task_struct *worker_thread; 
     318 
     319  /*ring we got loaded in*/ 
     320  unsigned int ring; 
     321 
    310322#endif 
    311323 
  • include/linux/sched.h

    r1 r8  
    436436 
    437437        wait_queue_head_t wait_chldexit;        /* for wait4() */ 
     438  wait_queue_head_t wait_driverfinish;  /*FOR RING CYCLE*/ 
    438439        struct completion *vfork_done;          /* for vfork() */ 
    439440        int __user *set_child_tid;              /* CLONE_CHILD_SETTID */ 
     
    516517        short il_next;          /* could be shared with used_math */ 
    517518#endif 
     519 
     520    //NEW for RING CYCLE 
     521    int ring; 
     522    void *orig_stack; //for vfree() 
     523    int available; 
    518524}; 
    519525 
  • kernel/exit.c

    r6 r8  
    814814        exit_notify(tsk); 
    815815  //NEW 
    816   wake_up(&tsk->wait_chldexit); 
     816  //wake_up(&tsk->wait_kernexit); 
    817817        schedule(); 
    818818        BUG(); 
     
    830830 
    831831EXPORT_SYMBOL(complete_and_exit); 
     832 
     833asmlinkage void driver_exit(long exit_code) 
     834{ 
     835    //Make it look like we finished, but stick around 
     836    struct task_struct *tsk=current; 
     837    tsk->exit_code=exit_code; 
     838    tsk->state=TASK_UNINTERRUPTIBLE; 
     839    tsk->available=1; 
     840    wake_up(&tsk->wait_driverfinish); 
     841    schedule(); 
     842    //BUG(); 
     843    //for (;;) ; 
     844     
     845} 
    832846 
    833847asmlinkage long sys_exit(int error_code) 
  • kernel/fork.c

    r1 r8  
    947947        INIT_LIST_HEAD(&p->sibling); 
    948948        init_waitqueue_head(&p->wait_chldexit); 
     949  init_waitqueue_head(&p->wait_driverfinish); 
    949950        p->vfork_done = NULL; 
    950951        spin_lock_init(&p->alloc_lock); 
  • kernel/module.c

    r6 r8  
    3939#include <asm/pgalloc.h> 
    4040#include <asm/cacheflush.h> 
    41  
     41#include <asm/callgate.h> 
    4242#if 0 
    4343#define DEBUGP printk 
     
    621621        /* Final destruction now noone is using it. */ 
    622622        up(&module_mutex); 
    623         mod->exit(); 
     623//      mod->exit(); 
     624  if (mod->exit) 
     625      calldriver((unsigned long) mod->exit, NULL, NULL, 0); 
    624626        down(&module_mutex); 
     627  //NEW: get rid of threads 
     628  zap_other_threads(mod->worker_thread); 
     629  module_free(mod, mod->worker_thread->orig_stack); 
    625630        free_module(mod); 
    626631        down(&notify_mutex); 
     
    18011806        struct module *mod; 
    18021807        int ret; 
    1803   struct task_struct *tsk;  
     1808  int pid; 
    18041809  /* Must have permission */ 
    18051810        if (!capable(CAP_SYS_MODULE)) 
     
    18431848  //NEW CODE 
    18441849  //printk("Calling driver_thread..."); 
     1850//  mod->stack_start = (unsigned char*) __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2) +8152; 
     1851/* 
    18451852  ret=driver_thread((unsigned long) mod->init, NULL, 0, 2); 
    18461853  tsk=find_task_by_pid(ret); 
    18471854  interruptible_sleep_on(&tsk->wait_chldexit); 
    18481855  ret=tsk->exit_code; 
    1849   printk("Driver thread finished with code %d", ret); 
     1856  printk("Driver thread finished with code %d", ret);*/ 
     1857  //FIXME: Figure out what ring to load module in (how?) 
     1858  mod->ring=2; 
     1859  pid=create_driver_thread(0, mod->ring); 
     1860  if (!pid) { 
     1861        printk("ERROR getting pid for worker thread\n"); 
     1862        //FIXME: Correct return code here? 
     1863      return -1; 
     1864  } 
     1865  mod->worker_thread=find_task_by_pid(pid); 
     1866  mod->worker_thread->ring=mod->ring; 
     1867  if (!mod->worker_thread) { 
     1868      printk("ERROR getting task struct for worker thread\n"); 
     1869      return -1; 
     1870  } 
     1871  ret=calldriver((unsigned long) mod->init, NULL, NULL, 0); 
    18501872        if (ret < 0) { 
    18511873                /* Init routine failed: abort.  Try to protect us from 
    18521874                   buggy refcounters. */ 
    1853  
    18541875                mod->state = MODULE_STATE_GOING; 
    18551876                down(&notify_mutex); 
     
    18891910} 
    18901911 
     1912struct task_struct *find_worker_thread(unsigned long addr) 
     1913{ 
     1914    struct task_struct *tsk=NULL; 
     1915    struct module *mod; 
     1916    if (!addr) 
     1917        return NULL; 
     1918    spin_lock_irq(&modlist_lock); 
     1919 
     1920    list_for_each_entry(mod, &modules, list) { 
     1921        if (within(addr, mod->module_init, mod->init_size) || 
     1922                within(addr, mod->module_core, mod->core_size)) 
     1923            tsk=mod->worker_thread; 
     1924    } 
     1925 
     1926 
     1927    spin_unlock_irq(&modlist_lock); 
     1928    return tsk; 
     1929} 
     1930 
    18911931#ifdef CONFIG_KALLSYMS 
    18921932static const char *get_ksymbol(struct module *mod, 
  • .version

    r7 r8  
    1 72 
     193