fault.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #undef DBG
  16. #define DBG if(0)print
  17. char *faulttypes[] = {
  18. [FT_WRITE] "write",
  19. [FT_READ] "read",
  20. [FT_EXEC] "exec"
  21. };
  22. /*
  23. * Fault calls fixfault which ends up calling newpage, which
  24. * might fail to allocate a page for the right color. So, we
  25. * might enter a loop and retry forever.
  26. * We first try with the desired color, and then with any
  27. * other one, if we failed for some time.
  28. */
  29. int
  30. fault(uintptr_t addr, uintptr_t pc, int ftype)
  31. {
  32. Proc *up = externup();
  33. Segment *s;
  34. char *sps;
  35. int i, color;
  36. if(up->nlocks)
  37. print("%s fault nlocks %d addr %p pc %p\n",
  38. faulttypes[ftype],
  39. up->nlocks,
  40. addr, pc);
  41. sps = up->psstate;
  42. up->psstate = "Fault";
  43. spllo();
  44. machp()->pfault++;
  45. for(i = 0;; i++) {
  46. s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */
  47. //print("%s fault seg for %p is %p base %p top %p\n", faulttypes[ftype], addr, s, s->base, s->top);
  48. if(s == nil)
  49. goto fail;
  50. if(ftype == FT_READ && (s->type&SG_READ) == 0)
  51. goto fail;
  52. if(ftype == FT_WRITE && (s->type&SG_WRITE) == 0)
  53. goto fail;
  54. if(ftype == FT_EXEC && (s->type&SG_EXEC) == 0)
  55. goto fail;
  56. color = s->color;
  57. if(i > 3)
  58. color = -1;
  59. if(fixfault(s, addr, ftype, 1, color) == 0)
  60. break;
  61. /*
  62. * See the comment in newpage that describes
  63. * how to get here.
  64. */
  65. if(i > 0 && (i%1000) == 0)
  66. print("fault: tried %d times\n", i);
  67. }
  68. up->psstate = sps;
  69. return 0;
  70. fail:
  71. if(s != nil){
  72. qunlock(&s->lk);
  73. print("%s fault fail %s(%c%c%c) pid %d addr 0x%p pc 0x%p\n",
  74. faulttypes[ftype],
  75. segtypes[s->type & SG_TYPE],
  76. (s->type & SG_READ) != 0 ? 'r' : '-',
  77. (s->type & SG_WRITE) != 0 ? 'w' : '-',
  78. (s->type & SG_EXEC) != 0 ? 'x' : '-',
  79. up->pid, addr, pc);
  80. } else {
  81. print("%s fault fail, no segment, pid %d addr 0x%p pc 0x%p\n",
  82. faulttypes[ftype],
  83. up->pid, addr, pc);
  84. }
  85. up->psstate = sps;
  86. return -1;
  87. }
  88. static void
  89. faulterror(char *s, Chan *c, int freemem)
  90. {
  91. Proc *up = externup();
  92. char buf[ERRMAX];
  93. if(c && c->path){
  94. snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr);
  95. s = buf;
  96. }
  97. if(up->nerrlab) {
  98. postnote(up, 1, s, NDebug);
  99. error(s);
  100. }
  101. pexit(s, freemem);
  102. }
  103. int
  104. fixfault(Segment *s, uintptr_t addr, int ftype, int dommuput, int color)
  105. {
  106. Proc *up = externup();
  107. int stype;
  108. int ref;
  109. Pte **p, *etp;
  110. uintptr_t soff;
  111. uintmem pgsz;
  112. uint mmuattr;
  113. Page **pg, *lkp, *new;
  114. Page *(*fn)(Segment*, uintptr_t);
  115. pgsz = machp()->pgsz[s->pgszi];
  116. addr &= ~(pgsz-1);
  117. soff = addr-s->base;
  118. p = &s->map[soff/PTEMAPMEM];
  119. if(*p == 0)
  120. *p = ptealloc(s);
  121. etp = *p;
  122. pg = &etp->pages[(soff&(PTEMAPMEM-1))/pgsz];
  123. stype = s->type&SG_TYPE;
  124. if(pg < etp->first)
  125. etp->first = pg;
  126. if(pg > etp->last)
  127. etp->last = pg;
  128. mmuattr = 0;
  129. switch(stype) {
  130. default:
  131. panic("fault");
  132. break;
  133. case SG_BSS:
  134. case SG_SHARED: /* Zero fill on demand */
  135. case SG_STACK:
  136. if(*pg == 0) {
  137. new = newpage(1, &s, addr, pgsz, color);
  138. if(s == 0)
  139. return -1;
  140. *pg = new;
  141. }
  142. goto common;
  143. case SG_MMAP:
  144. print("MMAP fault: req is %p, \n", up->req);
  145. if(pagedout(*pg) && up->req) {
  146. print("Fault in mmap'ed page\n");
  147. // hazardous.
  148. char f[34];
  149. snprint(f, sizeof(f), "W%016x%016x", addr, pgsz);
  150. if (qwrite(up->req, f, sizeof(f)) != sizeof(f))
  151. error("can't write mmap request");
  152. /* read in answer here. */
  153. error("not reading answer yet");
  154. }
  155. error("No mmap support yet");
  156. goto common;
  157. case SG_LOAD:
  158. case SG_DATA:
  159. case SG_TEXT: /* Demand load */
  160. if(pagedout(*pg))
  161. pio(s, addr, soff, pg, color);
  162. common: /* Demand load/pagein/copy on write */
  163. if(ftype != FT_WRITE){
  164. /* never copy a non-writeable seg */
  165. if((s->type & SG_WRITE) == 0){
  166. mmuattr = PTERONLY|PTEVALID;
  167. if((s->type & SG_EXEC) == 0)
  168. mmuattr |= PTENOEXEC;
  169. (*pg)->modref = PG_REF;
  170. break;
  171. }
  172. /* delay copy if we are the only user (copy on write when it happens) */
  173. if(conf.copymode == 0 && s->ref == 1) {
  174. mmuattr = PTERONLY|PTEVALID;
  175. if((s->type & SG_EXEC) == 0)
  176. mmuattr |= PTENOEXEC;
  177. (*pg)->modref |= PG_REF;
  178. break;
  179. }
  180. }
  181. if((s->type & SG_WRITE) == 0)
  182. error("fixfault: write on read-only\n");
  183. if((s->type & SG_TYPE) != SG_SHARED){
  184. lkp = *pg;
  185. lock(lkp);
  186. ref = lkp->ref;
  187. if(ref > 1) { /* page is shared but segment is not: copy for write */
  188. int pgref = lkp->ref;
  189. unlock(lkp);
  190. DBG("fixfault %d: copy on %s, %s(%c%c%c) 0x%p segref %d pgref %d\n",
  191. up->pid,
  192. faulttypes[ftype],
  193. segtypes[stype],
  194. (s->type & SG_READ) != 0 ? 'r' : '-',
  195. (s->type & SG_WRITE) != 0 ? 'w' : '-',
  196. (s->type & SG_EXEC) != 0 ? 'x' : '-',
  197. addr,
  198. s->ref,
  199. pgref
  200. );
  201. // No need to zero here as it is copied
  202. // over.
  203. new = newpage(0, &s, addr, pgsz, color);
  204. if(s == 0)
  205. return -1;
  206. *pg = new;
  207. copypage(lkp, *pg);
  208. putpage(lkp);
  209. } else { /* write: don't dirty the image cache */
  210. if(lkp->image != nil)
  211. duppage(lkp);
  212. unlock(lkp);
  213. }
  214. }
  215. mmuattr = PTEVALID|PTEWRITE;
  216. if((s->type & SG_EXEC) == 0)
  217. mmuattr |= PTENOEXEC;
  218. (*pg)->modref = PG_MOD|PG_REF;
  219. break;
  220. case SG_PHYSICAL:
  221. if(*pg == 0) {
  222. fn = s->pseg->pgalloc;
  223. if(fn)
  224. *pg = (*fn)(s, addr);
  225. else {
  226. new = smalloc(sizeof(Page));
  227. new->va = addr;
  228. new->pa = s->pseg->pa+(addr-s->base);
  229. new->ref = 1;
  230. new->pgszi = s->pseg->pgszi;
  231. *pg = new;
  232. }
  233. }
  234. mmuattr = PTEVALID;
  235. if((s->pseg->attr & SG_WRITE) != 0)
  236. mmuattr |= PTEWRITE;
  237. if((s->pseg->attr & SG_CACHED) == 0)
  238. mmuattr |= PTEUNCACHED;
  239. if((s->type & SG_EXEC) == 0)
  240. mmuattr |= PTENOEXEC;
  241. (*pg)->modref = PG_MOD|PG_REF;
  242. break;
  243. }
  244. qunlock(&s->lk);
  245. if(dommuput){
  246. assert(segppn(s, (*pg)->pa) == (*pg)->pa);
  247. mmuput(addr, *pg, mmuattr);
  248. }
  249. return 0;
  250. }
  251. void
  252. pio(Segment *s, uintptr_t addr, uint32_t soff, Page **p, int color)
  253. {
  254. Proc *up = externup();
  255. Page *newpg;
  256. KMap *k;
  257. Chan *c;
  258. int n, ask;
  259. uintmem pgsz;
  260. char *kaddr;
  261. uint32_t daddr, doff;
  262. Page *loadrec;
  263. loadrec = *p;
  264. daddr = ask = 0;
  265. c = nil;
  266. pgsz = machp()->pgsz[s->pgszi];
  267. if(loadrec == nil) { /* from a text/data image */
  268. daddr = s->ldseg.pg0fileoff + soff;
  269. doff = s->ldseg.pg0off;
  270. if(soff < doff+s->ldseg.filesz){
  271. ask = doff+s->ldseg.filesz - soff;
  272. if(ask > pgsz)
  273. ask = pgsz;
  274. if(soff > 0)
  275. doff = 0;
  276. newpg = lookpage(s->image, daddr+doff);
  277. if(newpg != nil) {
  278. *p = newpg;
  279. return;
  280. }
  281. } else {
  282. // zero fill
  283. ask = 0;
  284. doff = 0;
  285. }
  286. c = s->image->c;
  287. } else {
  288. panic("no swap");
  289. }
  290. qunlock(&s->lk);
  291. // For plan 9 a.out format the amount of data
  292. // we read covered the page; the first parameter
  293. // of newpage here was 0 -- "don't zero".
  294. // It is now 1 -- "do zero" because ELF only covers
  295. // part of the page.
  296. newpg = newpage(1, nil, addr, pgsz, color);
  297. if(ask > doff){
  298. k = kmap(newpg);
  299. kaddr = (char*)VA(k);
  300. while(waserror()) {
  301. if(strcmp(up->errstr, Eintr) == 0)
  302. continue;
  303. kunmap(k);
  304. putpage(newpg);
  305. faulterror(Eioload, c, 0);
  306. }
  307. DBG(
  308. "pio %d %s(%c%c%c) addr+doff 0x%p daddr+doff 0x%x ask-doff %d\n",
  309. up->pid, segtypes[s->type & SG_TYPE],
  310. (s->type & SG_READ) != 0 ? 'r' : '-',
  311. (s->type & SG_WRITE) != 0 ? 'w' : '-',
  312. (s->type & SG_EXEC) != 0 ? 'x' : '-',
  313. addr+doff, daddr+doff, ask-doff
  314. );
  315. n = c->dev->read(c, kaddr+doff, ask-doff, daddr+doff);
  316. if(n != ask-doff)
  317. faulterror(Eioload, c, 0);
  318. poperror();
  319. kunmap(k);
  320. }
  321. qlock(&s->lk);
  322. if(loadrec == nil) { /* This is demand load */
  323. /*
  324. * race, another proc may have gotten here first while
  325. * s->lk was unlocked
  326. */
  327. if(*p == nil) {
  328. // put it to page cache if there was i/o for it
  329. if(ask > doff){
  330. newpg->daddr = daddr+doff;
  331. cachepage(newpg, s->image);
  332. }
  333. *p = newpg;
  334. } else {
  335. print("racing on demand load\n");
  336. putpage(newpg);
  337. }
  338. } else {
  339. panic("no swap");
  340. }
  341. if(s->flushme)
  342. memset((*p)->cachectl, PG_TXTFLUSH, sizeof((*p)->cachectl));
  343. }
  344. /*
  345. * Called only in a system call
  346. */
  347. int
  348. okaddr(uintptr_t addr, int32_t len, int write)
  349. {
  350. Proc *up = externup();
  351. Segment *s;
  352. if(len >= 0) {
  353. for(;;) {
  354. s = seg(up, addr, 0);
  355. if(s == 0 || (write && (s->type&SG_WRITE) == 0))
  356. break;
  357. if(addr+len > s->top) {
  358. len -= s->top - addr;
  359. addr = s->top;
  360. continue;
  361. }
  362. return 1;
  363. }
  364. }
  365. return 0;
  366. }
  367. void*
  368. validaddr(void* addr, int32_t len, int write)
  369. {
  370. if(!okaddr(PTR2UINT(addr), len, write)){
  371. pprint("suicide: invalid address %#p/%ld in sys call pc=%#p\n",
  372. addr, len, userpc(nil));
  373. pexit("Suicide", 0);
  374. }
  375. return UINT2PTR(addr);
  376. }
  377. /*
  378. * &s[0] is known to be a valid address.
  379. * Assume 2M pages, so it works for both 2M and 1G pages.
  380. * Note this won't work for 4*KiB pages!
  381. */
  382. void*
  383. vmemchr(void *s, int c, int n)
  384. {
  385. int m;
  386. uintptr_t a;
  387. char *t;
  388. a = PTR2UINT(s);
  389. while(ROUNDUP(a, BIGPGSZ) != ROUNDUP(a+n-1, BIGPGSZ)){
  390. /* spans pages; handle this page */
  391. m = BIGPGSZ - (a & (BIGPGSZ-1));
  392. // t = memchr(UINT2PTR(a), c, m);
  393. for(t = UINT2PTR(a); m > 0; m--, t++)
  394. if (*t == c)
  395. break;
  396. if(*t == c)
  397. return t;
  398. a += m;
  399. n -= m;
  400. /* N.B. You're either going to find the character
  401. * or validaddr will error() and bounce you way back
  402. * up the call chain. That's why there's no worry about
  403. * returning NULL.
  404. */
  405. if((a & KZERO) != KZERO)
  406. validaddr(UINT2PTR(a), 1, 0);
  407. }
  408. /* fits in one page */
  409. for(t = UINT2PTR(a); n > 0; n--, t++)
  410. if (*t == c)
  411. break;
  412. if(*t != c)
  413. error("Bogus string");
  414. return t;
  415. }
  416. Segment*
  417. seg(Proc *p, uintptr_t addr, int dolock)
  418. {
  419. Segment **s, **et, *n;
  420. et = &p->seg[NSEG];
  421. for(s = p->seg; s < et; s++) {
  422. n = *s;
  423. if(n == 0)
  424. continue;
  425. if(addr >= n->base && addr < n->top) {
  426. if(dolock == 0)
  427. return n;
  428. qlock(&n->lk);
  429. if(addr >= n->base && addr < n->top)
  430. return n;
  431. qunlock(&n->lk);
  432. }
  433. }
  434. return 0;
  435. }