00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <types.h>
00031 #include <kern/errno.h>
00032 #include <lib.h>
00033 #include <spl.h>
00034 #include <spinlock.h>
00035 #include <proc.h>
00036 #include <current.h>
00037 #include <mips/tlb.h>
00038 #include <addrspace.h>
00039 #include <vm.h>
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #define DUMBVM_STACKPAGES 12
00050
00051
00052
00053
00054 static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
00055
00056 void
00057 vm_bootstrap(void)
00058 {
00059
00060 }
00061
00062 static
00063 paddr_t
00064 getppages(unsigned long npages)
00065 {
00066 paddr_t addr;
00067
00068 spinlock_acquire(&stealmem_lock);
00069
00070 addr = ram_stealmem(npages);
00071
00072 spinlock_release(&stealmem_lock);
00073 return addr;
00074 }
00075
00076
00077 vaddr_t
00078 alloc_kpages(int npages)
00079 {
00080 paddr_t pa;
00081 pa = getppages(npages);
00082 if (pa==0) {
00083 return 0;
00084 }
00085 return PADDR_TO_KVADDR(pa);
00086 }
00087
00088 void
00089 free_kpages(vaddr_t addr)
00090 {
00091
00092
00093 (void)addr;
00094 }
00095
00096 void
00097 vm_tlbshootdown_all(void)
00098 {
00099 panic("dumbvm tried to do tlb shootdown?!\n");
00100 }
00101
00102 void
00103 vm_tlbshootdown(const struct tlbshootdown *ts)
00104 {
00105 (void)ts;
00106 panic("dumbvm tried to do tlb shootdown?!\n");
00107 }
00108
00109 int
00110 vm_fault(int faulttype, vaddr_t faultaddress)
00111 {
00112 vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
00113 paddr_t paddr;
00114 int i;
00115 uint32_t ehi, elo;
00116 struct addrspace *as;
00117 int spl;
00118
00119 faultaddress &= PAGE_FRAME;
00120
00121 DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
00122
00123 switch (faulttype) {
00124 case VM_FAULT_READONLY:
00125
00126 panic("dumbvm: got VM_FAULT_READONLY\n");
00127 case VM_FAULT_READ:
00128 case VM_FAULT_WRITE:
00129 break;
00130 default:
00131 return EINVAL;
00132 }
00133
00134 if (curproc == NULL) {
00135
00136
00137
00138
00139
00140 return EFAULT;
00141 }
00142
00143 as = curproc_getas();
00144 if (as == NULL) {
00145
00146
00147
00148
00149 return EFAULT;
00150 }
00151
00152
00153 KASSERT(as->as_vbase1 != 0);
00154 KASSERT(as->as_pbase1 != 0);
00155 KASSERT(as->as_npages1 != 0);
00156 KASSERT(as->as_vbase2 != 0);
00157 KASSERT(as->as_pbase2 != 0);
00158 KASSERT(as->as_npages2 != 0);
00159 KASSERT(as->as_stackpbase != 0);
00160 KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
00161 KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
00162 KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
00163 KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
00164 KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
00165
00166 vbase1 = as->as_vbase1;
00167 vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
00168 vbase2 = as->as_vbase2;
00169 vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
00170 stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
00171 stacktop = USERSTACK;
00172
00173 if (faultaddress >= vbase1 && faultaddress < vtop1) {
00174 paddr = (faultaddress - vbase1) + as->as_pbase1;
00175 }
00176 else if (faultaddress >= vbase2 && faultaddress < vtop2) {
00177 paddr = (faultaddress - vbase2) + as->as_pbase2;
00178 }
00179 else if (faultaddress >= stackbase && faultaddress < stacktop) {
00180 paddr = (faultaddress - stackbase) + as->as_stackpbase;
00181 }
00182 else {
00183 return EFAULT;
00184 }
00185
00186
00187 KASSERT((paddr & PAGE_FRAME) == paddr);
00188
00189
00190 spl = splhigh();
00191
00192 for (i=0; i<NUM_TLB; i++) {
00193 tlb_read(&ehi, &elo, i);
00194 if (elo & TLBLO_VALID) {
00195 continue;
00196 }
00197 ehi = faultaddress;
00198 elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
00199 DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
00200 tlb_write(ehi, elo, i);
00201 splx(spl);
00202 return 0;
00203 }
00204
00205 kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
00206 splx(spl);
00207 return EFAULT;
00208 }
00209
00210 struct addrspace *
00211 as_create(void)
00212 {
00213 struct addrspace *as = kmalloc(sizeof(struct addrspace));
00214 if (as==NULL) {
00215 return NULL;
00216 }
00217
00218 as->as_vbase1 = 0;
00219 as->as_pbase1 = 0;
00220 as->as_npages1 = 0;
00221 as->as_vbase2 = 0;
00222 as->as_pbase2 = 0;
00223 as->as_npages2 = 0;
00224 as->as_stackpbase = 0;
00225
00226 return as;
00227 }
00228
00229 void
00230 as_destroy(struct addrspace *as)
00231 {
00232 kfree(as);
00233 }
00234
00235 void
00236 as_activate(void)
00237 {
00238 int i, spl;
00239 struct addrspace *as;
00240
00241 as = curproc_getas();
00242 #ifdef UW
00243
00244 #endif
00245 if (as == NULL) {
00246 return;
00247 }
00248
00249
00250 spl = splhigh();
00251
00252 for (i=0; i<NUM_TLB; i++) {
00253 tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
00254 }
00255
00256 splx(spl);
00257 }
00258
00259 void
00260 as_deactivate(void)
00261 {
00262
00263 }
00264
00265 int
00266 as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
00267 int readable, int writeable, int executable)
00268 {
00269 size_t npages;
00270
00271
00272 sz += vaddr & ~(vaddr_t)PAGE_FRAME;
00273 vaddr &= PAGE_FRAME;
00274
00275
00276 sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
00277
00278 npages = sz / PAGE_SIZE;
00279
00280
00281 (void)readable;
00282 (void)writeable;
00283 (void)executable;
00284
00285 if (as->as_vbase1 == 0) {
00286 as->as_vbase1 = vaddr;
00287 as->as_npages1 = npages;
00288 return 0;
00289 }
00290
00291 if (as->as_vbase2 == 0) {
00292 as->as_vbase2 = vaddr;
00293 as->as_npages2 = npages;
00294 return 0;
00295 }
00296
00297
00298
00299
00300 kprintf("dumbvm: Warning: too many regions\n");
00301 return EUNIMP;
00302 }
00303
00304 static
00305 void
00306 as_zero_region(paddr_t paddr, unsigned npages)
00307 {
00308 bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
00309 }
00310
00311 int
00312 as_prepare_load(struct addrspace *as)
00313 {
00314 KASSERT(as->as_pbase1 == 0);
00315 KASSERT(as->as_pbase2 == 0);
00316 KASSERT(as->as_stackpbase == 0);
00317
00318 as->as_pbase1 = getppages(as->as_npages1);
00319 if (as->as_pbase1 == 0) {
00320 return ENOMEM;
00321 }
00322
00323 as->as_pbase2 = getppages(as->as_npages2);
00324 if (as->as_pbase2 == 0) {
00325 return ENOMEM;
00326 }
00327
00328 as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
00329 if (as->as_stackpbase == 0) {
00330 return ENOMEM;
00331 }
00332
00333 as_zero_region(as->as_pbase1, as->as_npages1);
00334 as_zero_region(as->as_pbase2, as->as_npages2);
00335 as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
00336
00337 return 0;
00338 }
00339
00340 int
00341 as_complete_load(struct addrspace *as)
00342 {
00343 (void)as;
00344 return 0;
00345 }
00346
00347 int
00348 as_define_stack(struct addrspace *as, vaddr_t *stackptr)
00349 {
00350 KASSERT(as->as_stackpbase != 0);
00351
00352 *stackptr = USERSTACK;
00353 return 0;
00354 }
00355
00356 int
00357 as_copy(struct addrspace *old, struct addrspace **ret)
00358 {
00359 struct addrspace *new;
00360
00361 new = as_create();
00362 if (new==NULL) {
00363 return ENOMEM;
00364 }
00365
00366 new->as_vbase1 = old->as_vbase1;
00367 new->as_npages1 = old->as_npages1;
00368 new->as_vbase2 = old->as_vbase2;
00369 new->as_npages2 = old->as_npages2;
00370
00371
00372 if (as_prepare_load(new)) {
00373 as_destroy(new);
00374 return ENOMEM;
00375 }
00376
00377 KASSERT(new->as_pbase1 != 0);
00378 KASSERT(new->as_pbase2 != 0);
00379 KASSERT(new->as_stackpbase != 0);
00380
00381 memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
00382 (const void *)PADDR_TO_KVADDR(old->as_pbase1),
00383 old->as_npages1*PAGE_SIZE);
00384
00385 memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
00386 (const void *)PADDR_TO_KVADDR(old->as_pbase2),
00387 old->as_npages2*PAGE_SIZE);
00388
00389 memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
00390 (const void *)PADDR_TO_KVADDR(old->as_stackpbase),
00391 DUMBVM_STACKPAGES*PAGE_SIZE);
00392
00393 *ret = new;
00394 return 0;
00395 }