|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7:
8: void faulterror(char*);
9:
10: int
11: fault(ulong addr, int read)
12: {
13: Segment *s;
14: char *sps;
15:
16: sps = u->p->psstate;
17: u->p->psstate = "Fault";
18: spllo();
19:
20: m->pfault++;
21: for(;;) {
22: s = seg(u->p, addr, 1);
23: if(s == 0) {
24: u->p->psstate = sps;
25: return -1;
26: }
27:
28: if(!read && (s->type&SG_RONLY)) {
29: qunlock(&s->lk);
30: u->p->psstate = sps;
31: return -1;
32: }
33:
34: if(fixfault(s, addr, read, 1) == 0)
35: break;
36: }
37:
38: u->p->psstate = sps;
39: return 0;
40: }
41:
42: int
43: fixfault(Segment *s, ulong addr, int read, int doputmmu)
44: {
45: int type;
46: Pte **p, *etp;
47: ulong mmuphys=0, soff;
48: Page **pg, *lkp, *new;
49: Page *(*fn)(Segment*, ulong);
50:
51: addr &= ~(BY2PG-1);
52: soff = addr-s->base;
53: p = &s->map[soff/PTEMAPMEM];
54: if(*p == 0)
55: *p = ptealloc();
56:
57: etp = *p;
58: pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG];
59: type = s->type&SG_TYPE;
60:
61: if(pg < etp->first)
62: etp->first = pg;
63: if(pg > etp->last)
64: etp->last = pg;
65:
66: switch(type) {
67: default:
68: panic("fault");
69: break;
70:
71: case SG_TEXT:
72: if(pagedout(*pg)) /* Demand load */
73: pio(s, addr, soff, pg);
74:
75: mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
76: (*pg)->modref = PG_REF;
77: break;
78:
79: case SG_SHDATA: /* Shared data */
80: if(pagedout(*pg))
81: pio(s, addr, soff, pg);
82:
83: lkp = *pg;
84: lock(lkp);
85: if(lkp->image)
86: duppage(lkp);
87: unlock(lkp);
88: goto done;
89:
90: case SG_BSS:
91: case SG_SHARED: /* Zero fill on demand */
92: case SG_STACK:
93: if(*pg == 0) {
94: new = newpage(1, &s, addr);
95: if(s == 0)
96: return -1;
97:
98: *pg = new;
99: }
100: /* NO break */
101:
102: case SG_DATA: /* Demand load/pagein/copy on write */
103: if(pagedout(*pg))
104: pio(s, addr, soff, pg);
105:
106: if(type == SG_SHARED)
107: goto done;
108:
109: if(read && conf.copymode == 0) {
110: mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
111: (*pg)->modref |= PG_REF;
112: break;
113: }
114:
115: lkp = *pg;
116: lock(lkp);
117: if(lkp->ref > 1) {
118: unlock(lkp);
119: new = newpage(0, &s, addr);
120: if(s == 0)
121: return -1;
122: *pg = new;
123: copypage(lkp, *pg);
124: putpage(lkp);
125: }
126: else {
127: /* put a duplicate of a text page back onto the free list */
128: if(lkp->image)
129: duppage(lkp);
130:
131: unlock(lkp);
132: }
133: done:
134: mmuphys = PPN((*pg)->pa) | PTEWRITE|PTEVALID;
135: (*pg)->modref = PG_MOD|PG_REF;
136: break;
137:
138: case SG_PHYSICAL:
139: if(*pg == 0) {
140: fn = s->pseg->pgalloc;
141: if(fn)
142: *pg = (*fn)(s, addr);
143: else {
144: new = smalloc(sizeof(Page));
145: new->va = addr;
146: new->pa = s->pseg->pa+(addr-s->base);
147: new->ref = 1;
148: *pg = new;
149: }
150: }
151:
152: mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
153: (*pg)->modref = PG_MOD|PG_REF;
154: /* print("v %lux p %lux\n", addr, mmuphys); /**/
155: break;
156: }
157:
158: if(s->flushme)
159: memset((*pg)->cachectl, PG_TXTFLUSH, sizeof(new->cachectl));
160:
161: qunlock(&s->lk);
162:
163: if(doputmmu)
164: putmmu(addr, mmuphys, *pg);
165:
166: return 0;
167: }
168:
169: void
170: pio(Segment *s, ulong addr, ulong soff, Page **p)
171: {
172: Page *new;
173: KMap *k;
174: Chan *c;
175: int n, ask;
176: char *kaddr;
177: ulong daddr;
178: Page *loadrec;
179:
180: loadrec = *p;
181: if(loadrec == 0) {
182: daddr = s->fstart+soff; /* Compute disc address */
183: new = lookpage(s->image, daddr);
184: }
185: else {
186: daddr = swapaddr(loadrec);
187: new = lookpage(&swapimage, daddr);
188: if(new)
189: putswap(loadrec);
190: }
191:
192: if(new) { /* Page found from cache */
193: *p = new;
194: return;
195: }
196:
197: qunlock(&s->lk);
198:
199: new = newpage(0, 0, addr);
200: k = kmap(new);
201: kaddr = (char*)VA(k);
202:
203: if(loadrec == 0) { /* This is demand load */
204: c = s->image->c;
205: while(waserror()) {
206: if(strcmp(u->error, Eintr) == 0)
207: continue;
208: kunmap(k);
209: putpage(new);
210: faulterror("sys: demand load I/O error");
211: }
212:
213: ask = s->flen-soff;
214: if(ask > BY2PG)
215: ask = BY2PG;
216:
217: n = (*devtab[c->type].read)(c, kaddr, ask, daddr);
218: if(n != ask){
219: print("demand load: %s: %d %d\n", u->error, n, ask);
220: error(Eioload);
221: }
222: if(ask < BY2PG)
223: memset(kaddr+ask, 0, BY2PG-ask);
224:
225: poperror();
226: kunmap(k);
227: qlock(&s->lk);
228: if(*p == 0) { /* Someone may have got there first */
229: new->daddr = daddr;
230: cachepage(new, s->image);
231: *p = new;
232: }
233: else
234: putpage(new);
235: }
236: else { /* This is paged out */
237: c = swapimage.c;
238:
239: if(waserror()) {
240: kunmap(k);
241: putpage(new);
242: qlock(&s->lk);
243: qunlock(&s->lk);
244: faulterror("sys: page in I/O error");
245: }
246:
247: n = (*devtab[c->type].read)(c, kaddr, BY2PG, daddr);
248: if(n != BY2PG){
249: print("page in: %s: %d %d\n", u->error, n, BY2PG);
250: error(Eioload);
251: }
252:
253: poperror();
254: kunmap(k);
255: qlock(&s->lk);
256:
257: if(pagedout(*p)) {
258: new->daddr = daddr;
259: cachepage(new, &swapimage);
260: putswap(*p);
261: *p = new;
262: }
263: else
264: putpage(new);
265: }
266: }
267:
268: void
269: faulterror(char *s)
270: {
271: if(u->nerrlab) {
272: postnote(u->p, 1, s, NUser);
273: error(s);
274: }
275: pexit(s, 1);
276: }
277:
278: /*
279: * Called only in a system call
280: */
281: int
282: okaddr(ulong addr, ulong len, int write)
283: {
284: Segment *s;
285:
286: if((long)len >= 0) {
287: for(;;) {
288: s = seg(u->p, addr, 0);
289: if(s == 0 || (write && (s->type&SG_RONLY)))
290: break;
291:
292: if(addr+len > s->top) {
293: len -= s->top - addr;
294: addr = s->top;
295: continue;
296: }
297: return 1;
298: }
299: }
300: pprint("suicide: invalid address 0x%lux in sys call pc=0x%lux\n", addr, userpc());
301: return 0;
302: }
303:
304: void
305: validaddr(ulong addr, ulong len, int write)
306: {
307: if(!okaddr(addr, len, write))
308: pexit("Suicide", 0);
309: }
310:
311: /*
312: * &s[0] is known to be a valid address.
313: */
314: void*
315: vmemchr(void *s, int c, int n)
316: {
317: int m;
318: char *t;
319: ulong a;
320:
321: a = (ulong)s;
322: m = BY2PG - (a & (BY2PG-1));
323: if(m < n){
324: t = vmemchr(s, c, m);
325: if(t)
326: return t;
327: if(!(a & KZERO))
328: validaddr(a+m, 1, 0);
329: return vmemchr((void*)(a+m), c, n-m);
330: }
331: /*
332: * All in one page
333: */
334: return memchr(s, c, n);
335: }
336:
337: Segment*
338: seg(Proc *p, ulong addr, int dolock)
339: {
340: Segment **s, **et, *n;
341:
342: et = &p->seg[NSEG];
343: for(s = p->seg; s < et; s++)
344: if(n = *s){
345: if(addr >= n->base && addr < n->top) {
346: if(dolock == 0)
347: return n;
348:
349: qlock(&n->lk);
350: if(addr >= n->base && addr < n->top)
351: return n;
352: qunlock(&n->lk);
353: }
354: }
355:
356: return 0;
357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.