2 #include "../port/lib.h"
6 #include "../port/error.h"
9 faulterror(char *s, Chan *c)
14 snprint(buf, sizeof buf, "sys: %s accessing %s: %s", s, chanpath(c), up->errstr);
16 snprint(buf, sizeof buf, "sys: %s", s);
19 postnote(up, 1, buf, NDebug);
22 pprint("suicide: %s\n", buf);
27 pio(Segment *s, uintptr addr, uintptr soff, Page **p)
39 if(loadrec == nil) { /* from a text/data image */
40 daddr = s->fstart+soff;
41 new = lookpage(s->image, daddr);
51 else if((soff+ask) > s->flen)
54 else { /* from a swap image */
55 daddr = swapaddr(loadrec);
56 new = lookpage(&swapimage, daddr);
68 new = newpage(0, 0, addr);
72 if(strcmp(up->errstr, Eintr) == 0)
76 faulterror(Eioload, c);
78 n = devtab[c->type]->read(c, kaddr, ask, daddr);
82 memset(kaddr+ask, 0, BY2PG-ask);
87 if(loadrec == nil) { /* This is demand load */
89 * race, another proc may have gotten here first while
94 * check page cache again after i/o to reduce double caching
96 *p = lookpage(s->image, daddr);
100 cachepage(new, s->image);
105 else { /* This is paged out */
107 * race, another proc may have gotten here first
108 * (and the pager may have run on that page) while
113 /* another process did it for me */
115 } else if(*p != nil) {
116 /* another process and the pager got in */
120 /* another process segfreed the page */
123 memset((void*)VA(k), 0, ask);
132 cachepage(new, &swapimage);
143 fixfault(Segment *s, uintptr addr, int read)
146 uintptr soff, mmuphys;
147 Page **pg, *old, *new;
151 pte = &s->map[soff/PTEMAPMEM];
152 if((etp = *pte) == nil)
153 *pte = etp = ptealloc();
155 pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG];
161 switch(s->type & SG_TYPE) {
166 case SG_TEXT: /* Demand load */
168 pio(s, addr, soff, pg);
170 mmuphys = PPN((*pg)->pa) | PTERONLY | PTECACHED | PTEVALID;
171 (*pg)->modref = PG_REF;
175 case SG_SHARED: /* Zero fill on demand */
178 new = newpage(1, &s, addr);
184 case SG_DATA: /* Demand load/pagein/copy on write */
186 pio(s, addr, soff, pg);
189 * It's only possible to copy on write if
190 * we're the only user of the segment.
192 if(read && conf.copymode == 0 && s->ref == 1) {
193 mmuphys = PPN((*pg)->pa) | PTERONLY | PTECACHED | PTEVALID;
194 (*pg)->modref |= PG_REF;
199 if(old->image == &swapimage && (old->ref + swapcount(old->daddr)) == 1)
201 if(old->ref > 1 || old->image != nil) {
202 new = newpage(0, &s, addr);
212 case SG_STICKY: /* Never paged out */
213 mmuphys = PPN((*pg)->pa) | PTEWRITE | PTECACHED | PTEVALID;
214 (*pg)->modref = PG_MOD|PG_REF;
217 case SG_FIXED: /* Never paged out */
218 mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEUNCACHED | PTEVALID;
219 (*pg)->modref = PG_MOD|PG_REF;
224 if((s->type & SG_NOEXEC) != 0)
225 mmuphys |= PTENOEXEC;
230 putmmu(addr, mmuphys, *pg);
236 mapphys(Segment *s, uintptr addr, int attr)
244 pg.pa = s->pseg->pa+(addr-s->base);
246 mmuphys = PPN(pg.pa) | PTEVALID;
247 if((attr & SG_RONLY) == 0)
253 if((attr & SG_NOEXEC) != 0)
254 mmuphys |= PTENOEXEC;
258 if((attr & SG_DEVICE) != 0)
259 mmuphys |= PTEDEVICE;
262 if((attr & SG_CACHED) == 0)
263 mmuphys |= PTEUNCACHED;
265 mmuphys |= PTECACHED;
269 putmmu(addr, mmuphys, &pg);
273 fault(uintptr addr, uintptr pc, int read)
280 panic("fault: nil up");
282 Lock *l = up->lastlock;
283 print("fault: nlocks %d, proc %lud %s, addr %#p, lock %#p, lpc %#p\n",
284 up->nlocks, up->pid, up->text, addr, l, l ? l->pc : 0);
287 pnd = up->notepending;
289 up->psstate = "Fault";
295 s = seg(up, addr, 1); /* leaves s locked if seg != nil */
302 if((attr & SG_TYPE) == SG_PHYSICAL)
303 attr |= s->pseg->attr;
305 if((attr & SG_FAULT) != 0
306 || read? (attr & SG_NOEXEC) != 0 && (addr & -BY2PG) == (pc & -BY2PG):
307 (attr & SG_RONLY) != 0) {
310 if(up->kp && up->nerrlab) /* for segio */
315 if((attr & SG_TYPE) == SG_PHYSICAL){
316 mapphys(s, addr, attr);
320 if(fixfault(s, addr, read) == 0)
332 up->notepending |= pnd;
338 * Called only in a system call
341 okaddr(uintptr addr, ulong len, int write)
345 if((long)len >= 0 && len <= -addr) {
347 s = seg(up, addr, 0);
348 if(s == nil || (write && (s->type&SG_RONLY)))
351 if(addr+len > s->top) {
352 len -= s->top - addr;
363 validaddr(uintptr addr, ulong len, int write)
365 if(!okaddr(addr, len, write)){
366 pprint("suicide: invalid address %#p/%lud in sys call pc=%#p\n", addr, len, userpc());
367 postnote(up, 1, "sys: bad address in syscall", NDebug);
373 * &s[0] is known to be a valid address.
376 vmemchr(void *s, int c, ulong n)
384 m = BY2PG - (a & (BY2PG-1));
387 /* spans pages; handle this page */
388 t = memchr((void*)a, c, m);
397 /* fits in one page */
398 return memchr((void*)a, c, n);
402 seg(Proc *p, uintptr addr, int dolock)
404 Segment **s, **et, *n;
407 for(s = p->seg; s < et; s++) {
410 if(addr >= n->base && addr < n->top) {
415 if(addr >= n->base && addr < n->top)
424 extern void checkmmu(uintptr, uintptr);
432 Segment **sp, **ep, *s;
437 for(sp=up->seg, ep=&up->seg[NSEG]; sp<ep; sp++){
441 for(addr=s->base; addr<s->top; addr+=BY2PG){
442 off = addr - s->base;
443 if((p = s->map[off/PTEMAPMEM]) == nil)
445 pg = p->pages[(off&(PTEMAPMEM-1))/BY2PG];
448 checkmmu(addr, pg->pa);