00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <linux/mm.h>
00012 #include <linux/malloc.h>
00013 #include <linux/sched.h>
00014 #include <linux/kernel.h>
00015 #include <linux/kernel_stat.h>
00016 #include <linux/errno.h>
00017 #include <linux/string.h>
00018 #include <linux/stat.h>
00019 #include <linux/swap.h>
00020 #include <linux/fs.h>
00021 #include <linux/config.h>
00022 #include <linux/interrupt.h>
00023
00024 #include <asm/dma.h>
00025 #include <asm/system.h>
00026 #include <asm/segment.h>
00027 #include <asm/bitops.h>
00028 #include <asm/pgtable.h>
00029
00030 #define DEBUG 0
00031
00032 #define WRITE_LIMIT 100
00033 #define LOOP_LIMIT 200
00034
00035 static struct {
00036 int faults, read, write, success, failure, errors;
00037 } stats;
00038
00039
00040
00041
00042 static struct wait_queue * asyncd_wait = NULL;
00043
00044 struct async_job {
00045 volatile struct async_job *next;
00046 int taskid;
00047 struct mm_struct *mm;
00048 unsigned long address;
00049 int write;
00050 void (*callback)(int,unsigned long,int,int);
00051 };
00052
00053 static volatile struct async_job *async_queue = NULL;
00054 static volatile struct async_job *async_queue_end = NULL;
00055
00056 static void add_to_async_queue(int taskid,
00057 struct mm_struct *mm,
00058 unsigned long address,
00059 int write,
00060 void (*callback)(int,unsigned long,int,int))
00061 {
00062 struct async_job *a = kmalloc(sizeof(*a),GFP_ATOMIC);
00063
00064 if (!a) {
00065 printk("ERROR: out of memory in asyncd\n");
00066 a->callback(taskid,address,write,1);
00067 return;
00068 }
00069
00070 if (write)
00071 stats.write++;
00072 else
00073 stats.read++;
00074
00075 a->next = NULL;
00076 a->taskid = taskid;
00077 a->mm = mm;
00078 a->address = address;
00079 a->write = write;
00080 a->callback = callback;
00081
00082 if (!async_queue) {
00083 async_queue = a;
00084 } else {
00085 async_queue_end->next = a;
00086 }
00087 async_queue_end = a;
00088 }
00089
00090
00091 void async_fault(unsigned long address, int write, int taskid,
00092 void (*callback)(int,unsigned long,int,int))
00093 {
00094 struct task_struct *tsk = task[taskid];
00095 struct mm_struct *mm = tsk->mm;
00096
00097 stats.faults++;
00098
00099 #if 0
00100 printk("paging in %x for task=%d\n",address,taskid);
00101 #endif
00102
00103 add_to_async_queue(taskid, mm, address, write, callback);
00104 wake_up(&asyncd_wait);
00105 mark_bh(TQUEUE_BH);
00106 }
00107
00108 static int fault_in_page(int taskid,
00109 struct vm_area_struct *vma,
00110 unsigned address,int write)
00111 {
00112 static unsigned last_address;
00113 static int last_task, loop_counter;
00114 struct task_struct *tsk = task[taskid];
00115 pgd_t *pgd;
00116 pmd_t *pmd;
00117 pte_t *pte;
00118
00119 if (!tsk || !tsk->mm)
00120 return 1;
00121
00122 if (!vma || (write && !(vma->vm_flags & VM_WRITE)))
00123 goto bad_area;
00124 if (vma->vm_start > address)
00125 goto bad_area;
00126
00127 if (address == last_address && taskid == last_task) {
00128 loop_counter++;
00129 } else {
00130 loop_counter = 0;
00131 last_address = address;
00132 last_task = taskid;
00133 }
00134
00135 if (loop_counter == WRITE_LIMIT && !write) {
00136 printk("MSC bug? setting write request\n");
00137 stats.errors++;
00138 write = 1;
00139 }
00140
00141 if (loop_counter == LOOP_LIMIT) {
00142 printk("MSC bug? failing request\n");
00143 stats.errors++;
00144 return 1;
00145 }
00146
00147 pgd = pgd_offset(vma->vm_mm, address);
00148 pmd = pmd_alloc(pgd,address);
00149 if(!pmd)
00150 goto no_memory;
00151 pte = pte_alloc(pmd, address);
00152 if(!pte)
00153 goto no_memory;
00154 if(!pte_present(*pte)) {
00155 int fault = handle_mm_fault(tsk, vma, address, write);
00156 if (fault < 0)
00157 goto no_memory;
00158 goto finish_up;
00159 }
00160 set_pte(pte, pte_mkyoung(*pte));
00161 flush_tlb_page(vma, address);
00162 if(!write)
00163 goto finish_up;
00164 if(pte_write(*pte)) {
00165 set_pte(pte, pte_mkdirty(*pte));
00166 flush_tlb_page(vma, address);
00167 goto finish_up;
00168 }
00169 {
00170 int fault = handle_mm_fault(tsk, vma, address, write);
00171 if (fault < 0)
00172 goto no_memory;
00173 }
00174
00175
00176 finish_up:
00177 stats.success++;
00178 return 0;
00179
00180 no_memory:
00181 stats.failure++;
00182 force_sig(SIGKILL, tsk);
00183 return 1;
00184
00185 bad_area:
00186 stats.failure++;
00187 tsk->tss.sig_address = address;
00188 tsk->tss.sig_desc = SUBSIG_NOMAPPING;
00189 send_sig(SIGSEGV, tsk, 1);
00190 return 1;
00191 }
00192
00193
00194
00195
00196
00197 static void run_async_queue(void)
00198 {
00199 int ret;
00200 unsigned flags;
00201
00202 while (async_queue) {
00203 volatile struct async_job *a;
00204 struct mm_struct *mm;
00205 struct vm_area_struct *vma;
00206
00207 save_flags(flags); cli();
00208 a = async_queue;
00209 async_queue = async_queue->next;
00210 restore_flags(flags);
00211
00212 mm = a->mm;
00213
00214 down(&mm->mmap_sem);
00215 vma = find_vma(mm, a->address);
00216 ret = fault_in_page(a->taskid,vma,a->address,a->write);
00217 #if DEBUG
00218 printk("fault_in_page(task=%d addr=%x write=%d) = %d\n",
00219 a->taskid,a->address,a->write,ret);
00220 #endif
00221 a->callback(a->taskid,a->address,a->write,ret);
00222 up(&mm->mmap_sem);
00223 kfree_s((void *)a,sizeof(*a));
00224 }
00225 }
00226
00227
00228 #if CONFIG_AP1000
00229 static void asyncd_info(void)
00230 {
00231 printk("CID(%d) faults: total=%d read=%d write=%d success=%d fail=%d err=%d\n",
00232 mpp_cid(),stats.faults, stats.read, stats.write, stats.success,
00233 stats.failure, stats.errors);
00234 }
00235 #endif
00236
00237
00238
00239
00240
00241
00242 int asyncd(void *unused)
00243 {
00244 current->session = 1;
00245 current->pgrp = 1;
00246 sprintf(current->comm, "asyncd");
00247 sigfillset(¤t->blocked);
00248 recalc_sigpending(current);
00249
00250
00251 current->policy = SCHED_FIFO;
00252 current->priority = 32;
00253
00254
00255
00256 printk("Started asyncd\n");
00257
00258 #if CONFIG_AP1000
00259 bif_add_debug_key('a',asyncd_info,"stats on asyncd");
00260 #endif
00261
00262 while (1) {
00263 unsigned flags;
00264
00265 save_flags(flags); cli();
00266
00267 while (!async_queue) {
00268 spin_lock_irq(¤t->sigmask_lock);
00269 flush_signals(current);
00270 spin_unlock_irq(¤t->sigmask_lock);
00271 interruptible_sleep_on(&asyncd_wait);
00272 }
00273
00274 restore_flags(flags);
00275
00276 run_async_queue();
00277 }
00278 }
00279