|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.5 ! root 5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /*
14:
15: * mem.c:: routines for managing memory regions
16:
17: */
18:
19:
20:
21: #include "mint.h"
22:
1.1.1.3 root 23: #include "fasttext.h" /* for line A stuff */
24:
25:
26:
27: #ifndef VgetSize
28:
29: extern long xbios();
30:
31: #define VgetSize(mode) xbios(91, (short)(mode))
32:
33: #define Vsetmode(mode) xbios(88, (short)(mode))
34:
35: #endif
36:
1.1 root 37:
38:
39: static long core_malloc P_((long, int));
40:
1.1.1.3 root 41: static void core_free P_((long));
42:
1.1 root 43:
44:
45: /* macro for testing whether a memory region is free */
46:
47: #define ISFREE(m) ((m)->links == 0)
48:
49:
50:
51: /*
52:
1.1.1.2 root 53: * list of shared text regions currently being executed
54:
55: */
56:
57: SHTEXT *text_reg = 0;
58:
59:
60:
61: /*
62:
1.1 root 63: * initialize memory routines
64:
65: */
66:
67:
68:
69: /* initial number of memory regions */
70:
1.1.1.5 ! root 71: #define NREGIONS ((8*1024)/sizeof(MEMREGION))
1.1 root 72:
73:
74:
75: /* number of new regions to allocate when the initial ones are used up */
76:
1.1.1.5 ! root 77: #define NEWREGIONS ((8*1024)/sizeof(MEMREGION))
1.1 root 78:
79:
80:
81: static MEMREGION use_regions[NREGIONS+1];
82:
83: MEMREGION *rfreelist;
84:
85:
86:
1.1.1.5 ! root 87: /* variable for debugging purposes; number of times we've needed
! 88:
! 89: * to get new regions
! 90:
! 91: */
! 92:
! 93: int num_reg_requests = 0;
! 94:
! 95:
! 96:
1.1.1.3 root 97: /* these variables are set in init_core(), and used in
98:
99: * init_mem()
100:
101: */
102:
103: static ulong scrnsize, scrnplace;
104:
105: static SCREEN *vscreen;
106:
107:
108:
1.1 root 109: void
110:
111: init_mem()
112:
113: {
114:
115: int i;
116:
1.1.1.3 root 117: MEMREGION *r;
118:
119: long newbase;
120:
1.1 root 121:
122:
123: use_regions[NREGIONS].next = 0;
124:
125: for (i = 0; i < NREGIONS; i++) {
126:
127: use_regions[i].next = &use_regions[i+1];
128:
129: }
130:
131: rfreelist = use_regions;
132:
133:
134:
135: init_core();
136:
137: init_swap();
138:
1.1.1.3 root 139:
140:
141: init_tables(); /* initialize MMU constants */
142:
143:
144:
145: /* mark all the regions in the core & alt lists as "invalid" */
146:
147: for (r = *core; r; r = r->next) {
148:
149: mark_region(r,PROT_I);
150:
151: }
152:
153: for (r = *alt; r; r = r->next) {
154:
155: mark_region(r,PROT_I);
156:
157: }
158:
159:
160:
161: /* make sure the screen is set up properly */
162:
163: newbase = s_realloc(scrnsize);
164:
165:
166:
167: /* if we did get a new screen, point the new screen
168:
169: * at the right place after copying the data
170:
171: * if possible, save the screen to another buffer,
172:
173: * since if the new screen and old screen overlap
174:
175: * the blit will look very ugly.
176:
177: * Note that if the screen isn't moveable, then we set
178:
179: * scrnsize to a ridiculously large value, and so the
180:
181: * s_realloc above failed.
182:
183: */
184:
185: if (newbase) {
186:
187: /* find a free region for temp storage */
188:
189: for (r = *core; r; r = r->next) {
190:
191: if (ISFREE(r) && r->len >= scrnsize)
192:
193: break;
194:
195: }
196:
197:
198:
199: if (r) {
200:
201: quickmove((char *)r->loc, (char *)scrnplace, scrnsize);
202:
203: Setscreen((void *)r->loc, (void *)r->loc, -1);
204:
205: Vsync();
206:
207: quickmove((char *)newbase, (char *)r->loc, scrnsize);
208:
209: } else {
210:
211: quickmove((char *)newbase, (char *)scrnplace, scrnsize);
212:
213: }
214:
215: Setscreen((void *)newbase, (void *)newbase, -1);
216:
217: /* fix the cursor */
218:
219: Cconws("\r\n");
220:
221: }
222:
1.1 root 223: }
224:
225:
226:
1.1.1.5 ! root 227: void
! 228:
! 229: restr_screen()
! 230:
! 231: {
! 232:
! 233: long base = (long) Physbase ();
! 234:
! 235: MEMREGION *r;
! 236:
! 237:
! 238:
! 239: if (base != scrnplace)
! 240:
! 241: {
! 242:
! 243: for (r = *core; r; r = r->next)
! 244:
! 245: {
! 246:
! 247: if (ISFREE (r) && r->len >= scrnsize)
! 248:
! 249: break;
! 250:
! 251: }
! 252:
! 253: if (r)
! 254:
! 255: {
! 256:
! 257: quickmove ((char *) r->loc, (char *) base, scrnsize);
! 258:
! 259: Setscreen ((void *) r->loc, (void *) r->loc, -1);
! 260:
! 261: Vsync ();
! 262:
! 263: quickmove ((char *) scrnplace, (char *) r->loc, scrnsize);
! 264:
! 265: }
! 266:
! 267: else
! 268:
! 269: quickmove ((char *) scrnplace, (char *) base, scrnsize);
! 270:
! 271: Setscreen ((void *) scrnplace, (void *) scrnplace, -1);
! 272:
! 273: Cconws ("\r\n");
! 274:
! 275: }
! 276:
! 277: }
! 278:
! 279:
! 280:
1.1 root 281: /*
282:
283: * init_core(): initialize the core memory map (normal ST ram) and also
284:
285: * the alternate memory map (fast ram on the TT)
286:
287: */
288:
289:
290:
291: static MEMREGION *_core_regions = 0, *_alt_regions = 0,
292:
293: *_ker_regions = 0;
294:
295:
296:
297: MMAP core = &_core_regions;
298:
299: MMAP alt = &_alt_regions;
300:
301: MMAP ker = &_ker_regions;
302:
303:
304:
305: /* note: add_region must adjust both the size and starting
306:
307: * address of the region being added so that memory is
308:
309: * always properly aligned
310:
311: */
312:
313:
314:
315: int
316:
317: add_region(map, place, size, mflags)
318:
319: MMAP map;
320:
321: ulong place, size;
322:
323: unsigned mflags; /* initial flags for region */
324:
325: {
326:
1.1.1.3 root 327: MEMREGION *m;
1.1 root 328:
1.1.1.3 root 329: ulong trimsize;
1.1 root 330:
331:
332:
1.1.1.3 root 333: TRACELOW(("add_region(map=%lx,place=%lx,size=%lx,flags=%x)",
1.1 root 334:
1.1.1.3 root 335: map,place,size,mflags));
1.1 root 336:
337:
338:
339: m = new_region();
340:
341: if (m == 0)
342:
343: return 0; /* failure */
344:
345: m->links = 0;
346:
347:
348:
1.1.1.3 root 349: if (place & MASKBITS) {
350:
351: /* increase place & shorten size by the amount we're trimming */
352:
353: trimsize = (MASKBITS+1) - (place & MASKBITS);
354:
355: if (size <= trimsize) goto lose;
356:
357: size -= trimsize;
358:
359: place += trimsize;
360:
361: }
362:
363:
364:
365: /* now trim size DOWN to a multiple of pages */
366:
367: if (size & MASKBITS) size &= ~MASKBITS;
368:
369:
370:
371: /* only add if there's anything left */
372:
373: if (size) {
374:
375: m->len = size;
1.1 root 376:
1.1.1.3 root 377: m->loc = place;
378:
379: m->next = *map;
380:
381: m->mflags = mflags;
382:
383: *map = m;
384:
385: }
386:
387: else {
1.1 root 388:
1.1.1.3 root 389: /* succeed but don't do anything; dispose of region */
390:
391: lose: dispose_region(m);
392:
393: }
1.1 root 394:
395: return 1; /* success */
396:
397: }
398:
399:
400:
401: static long
402:
403: core_malloc(amt, mode)
404:
405: long amt;
406:
407: int mode;
408:
409: {
410:
411: static int mxalloc = -1; /* does GEMDOS know about Mxalloc? */
412:
413: long ret;
414:
415:
416:
417: if (mxalloc < 0) {
418:
419: ret = (long)Mxalloc(-1L, 0);
420:
421: if (ret == -32) mxalloc = 0; /* unknown function */
422:
423: else if (ret >= 0) mxalloc = 1;
424:
425: else {
426:
427: ALERT("GEMDOS returned %ld from Mxalloc", ret);
428:
429: mxalloc = 0;
430:
431: }
432:
433: }
434:
435: if (mxalloc)
436:
1.1.1.4 root 437: return (long) Mxalloc(amt, mode);
1.1 root 438:
439: else if (mode == 1)
440:
441: return 0L;
442:
443: else
444:
1.1.1.4 root 445: return (long) Malloc(amt);
1.1 root 446:
447: }
448:
449:
450:
1.1.1.3 root 451: static void
452:
453: core_free(where)
454:
455: long where;
456:
457: {
458:
459: Mfree((void *)where);
460:
461: }
462:
463:
464:
1.1 root 465: void
466:
467: init_core()
468:
469: {
470:
1.1.1.3 root 471: extern int FalconVideo; /* set in main.c */
472:
473: int scrndone = 0;
474:
1.1 root 475: ulong size;
476:
477: ulong place;
478:
1.1.1.3 root 479: ulong temp;
480:
1.1 root 481: void *tossave;
482:
483:
484:
485: tossave = (void *)core_malloc((long)TOS_MEM, 0);
486:
487: if (!tossave) {
488:
489: FATAL("Not enough memory to run MiNT");
490:
491: }
492:
493:
494:
495: /* initialize kernel memory */
496:
497: place = (ulong)core_malloc(KERNEL_MEM, 3);
498:
499: if (place != 0) {
500:
1.1.1.3 root 501: nalloc_arena_add((void *)place,KERNEL_MEM);
502:
503: }
504:
505:
506:
507: /*
508:
509: * find out where the screen is. We want to manage the screen
510:
511: * memory along with all the other memory, so that Srealloc()
512:
513: * can be used by the XBIOS to allocate screens from the
514:
515: * end of memory -- this avoids fragmentation problems when
516:
517: * changing resolutions.
518:
519: */
520:
521: /* Note, however, that some graphics boards (e.g. Matrix)
522:
523: * are unable to change the screen address. We fake out the
524:
525: * rest of our code by pretending to have a really huge
526:
527: * screen that can't be changed.
528:
529: */
530:
531: scrnplace = (long)Physbase();
532:
533:
534:
535: vscreen = (SCREEN *)((char *)lineA0() - 346);
536:
537: if (FalconVideo) {
538:
539: /* the Falcon can tell us the screen size */
540:
541: scrnsize = VgetSize(Vsetmode(-1));
542:
543: } else {
544:
545: /* otherwise, use the line A variables */
546:
547: scrnsize = (vscreen->maxy+1)*(long)vscreen->linelen;
548:
549: }
550:
551:
552:
553: /* check for a graphics card with fixed screen location */
554:
555: #define phys_top_st (*(ulong *)0x42eL)
556:
557:
558:
559: if (scrnplace >= phys_top_st) {
560:
561: /* screen isn't in ST RAM */
562:
563: scrnsize = 0x7fffffffUL;
564:
565: scrndone = 1;
566:
567: } else {
568:
569: temp = (ulong)core_malloc(scrnsize+256L, 0);
570:
571: if (temp) {
572:
573: (void)Setscreen((void *)-1L,
574:
575: (void *)((temp+511)&(0xffffff00L)), -1);
576:
1.1.1.4 root 577: if ((long)Physbase() != ((temp+511)&(0xffffff00L))) {
1.1.1.3 root 578:
579: scrnsize = 0x7fffffffUL;
580:
581: scrndone = 1;
582:
583: }
584:
585: (void)Setscreen((void *)-1L, (void *)scrnplace, -1);
586:
587: core_free(temp);
588:
589: }
1.1 root 590:
591: }
592:
593:
594:
595: /* initialize ST RAM */
596:
597: size = (ulong)core_malloc(-1L, 0);
598:
599: while (size > 0) {
600:
601: place = (ulong)core_malloc(size, 0);
602:
1.1.1.5 ! root 603: if (!scrndone && (place + size == scrnplace)) {
1.1.1.3 root 604:
605: size += scrnsize;
606:
607: scrndone = 1;
608:
609: }
610:
1.1 root 611: if (!add_region(core, place, size, M_CORE))
612:
613: FATAL("init_mem: unable to add a region");
614:
615: size = (ulong)core_malloc(-1L, 0);
616:
617: }
618:
619:
620:
1.1.1.3 root 621: if (!scrndone) {
622:
623: (void)add_region(core, scrnplace, scrnsize, M_CORE);
624:
625: }
626:
627:
628:
1.1 root 629: /* initialize alternate RAM */
630:
631: size = (ulong)core_malloc(-1L, 1);
632:
633: while (size > 0) {
634:
635: place = (ulong)core_malloc(size, 1);
636:
637: if (!add_region(alt, place, size, M_ALT))
638:
639: FATAL("init_mem: unable to add a region");
640:
641: size = (ulong)core_malloc(-1L, 1);
642:
643: }
644:
645:
646:
647: (void)Mfree(tossave); /* leave some memory for TOS to use */
648:
649: }
650:
651:
652:
653: /*
654:
655: * init_swap(): initialize the swap area; for now, this does nothing
656:
657: */
658:
659:
660:
661: MEMREGION *_swap_regions = 0;
662:
663: MMAP swap = &_swap_regions;
664:
665:
666:
667: void
668:
669: init_swap()
670:
671: {
672:
673: }
674:
675:
676:
677: /*
678:
679: * routines for allocating/deallocating memory regions
680:
681: */
682:
683:
684:
685: /*
686:
687: * new_region returns a new memory region descriptor, or NULL
688:
689: */
690:
691:
692:
693: MEMREGION *
694:
695: new_region()
696:
697: {
698:
699: MEMREGION *m, *newfrees;
700:
701: int i;
702:
703:
704:
705: m = rfreelist;
706:
707: if (!m) {
708:
709: ALERT("new_region: ran out of free regions");
710:
711: return 0;
712:
713: }
714:
715: assert(ISFREE(m));
716:
717: rfreelist = m->next;
718:
719: m->next = 0;
720:
721:
722:
723: /* if we're running low on free regions, allocate some more
724:
725: * we have to do this with at least 1 free region left so that get_region
726:
727: * has a chance of working
728:
729: */
730:
731: if (rfreelist && !rfreelist->next) {
732:
733: MEMREGION *newstuff;
734:
735:
736:
1.1.1.3 root 737: TRACELOW(("get_region: getting new region descriptors"));
1.1 root 738:
1.1.1.3 root 739: newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 740:
741: if (!newstuff)
742:
1.1.1.3 root 743: newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 744:
745: if (!newstuff)
746:
1.1.1.3 root 747: newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1 root 748:
749: newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
750:
751: if (newfrees) {
752:
1.1.1.5 ! root 753: num_reg_requests++;
! 754:
1.1 root 755: newfrees[NEWREGIONS-1].next = 0;
756:
757: newfrees[NEWREGIONS-1].links = 0;
758:
759: for (i = 0; i < NEWREGIONS-1; i++) {
760:
761: newfrees[i].next = &newfrees[i+1];
762:
763: newfrees[i].links = 0;
764:
765: }
766:
767: rfreelist = newfrees;
768:
769: } else {
770:
1.1.1.2 root 771: DEBUG(("couldn't get new region descriptors!"));
1.1 root 772:
773: }
774:
775: }
776:
777:
778:
779: return m;
780:
781: }
782:
783:
784:
785: /*
786:
787: * dispose_region destroys a memory region descriptor
788:
789: */
790:
791:
792:
793: void
794:
795: dispose_region(m)
796:
797: MEMREGION *m;
798:
799: {
800:
801: m->next = rfreelist;
802:
803: rfreelist = m;
804:
805: }
806:
807:
808:
809: /*
810:
1.1.1.3 root 811: * change_prot_status: change the status of a region to 'newmode'. We're
812:
813: * given its starting address, not its region structure pointer, so we have
814:
815: * to find the region pointer; since this is illegal if proc doesn't own
816:
817: * the region, we know we'll find the region struct pointer in proc->mem.
818:
819: *
820:
821: * If the proc doesn't own it, you get EACCDN. There are no other errors.
822:
823: * God help you if newmode isn't legal!
824:
825: */
826:
827:
828:
829: long
830:
831: change_prot_status(proc,start,newmode)
832:
833: PROC *proc;
834:
835: long start;
836:
837: int newmode;
838:
839: {
840:
841: MEMREGION **mr;
842:
843: int i;
844:
845:
846:
847: /* return EACCDN if you don't own the region in question */
848:
849: if (!proc->mem) return EACCDN;
850:
851:
852:
853: for (mr = proc->mem, i = 0; i < proc->num_reg; i++, mr++) {
854:
855: if ((*mr)->loc == start) goto found;
856:
857: }
858:
859: return EACCDN;
860:
861:
862:
863: found:
864:
865: mark_region(*mr,newmode);
866:
867: return E_OK;
868:
869: }
870:
871:
872:
873: /*
874:
1.1 root 875: * virtaddr
876:
877: * attach_region(proc, reg): attach the region to the given process:
878:
879: * returns the address at which it was attached, or NULL if the process
880:
881: * cannot attach more regions. The region link count is incremented if
882:
883: * the attachment is successful.
884:
885: */
886:
887:
888:
889: virtaddr
890:
891: attach_region(proc, reg)
892:
893: PROC *proc;
894:
895: MEMREGION *reg;
896:
897: {
898:
899: int i;
900:
901: MEMREGION **newmem;
902:
903: virtaddr *newaddr;
904:
905:
906:
1.1.1.3 root 907: TRACELOW(("attach_region %lx len %lx to pid %d",
908:
909: reg->loc, reg->len, proc->pid));
910:
911:
912:
1.1 root 913: if (!reg || !reg->loc) {
914:
915: ALERT("attach_region: attaching a null region??");
916:
917: return 0;
918:
919: }
920:
1.1.1.3 root 921:
922:
923: again:
924:
1.1 root 925: for (i = 0; i < proc->num_reg; i++) {
926:
927: if (!proc->mem[i]) {
928:
929: assert(proc->addr[i] == 0);
930:
931: reg->links++;
932:
933: proc->mem[i] = reg;
934:
935: proc->addr[i] = (virtaddr) reg->loc;
936:
1.1.1.5 ! root 937: mark_proc_region(proc,reg,PROT_P);
1.1.1.3 root 938:
1.1 root 939: return proc->addr[i];
940:
941: }
942:
943: }
944:
945:
946:
947: /* Hmmm, OK, we have to expand the process' memory table */
948:
1.1.1.3 root 949: TRACELOW(("Expanding process memory table"));
1.1 root 950:
951: i = proc->num_reg + NUM_REGIONS;
952:
953:
954:
955: newmem = kmalloc(i * SIZEOF(MEMREGION *));
956:
957: newaddr = kmalloc(i * SIZEOF(virtaddr));
958:
959:
960:
961: if (newmem && newaddr) {
962:
1.1.1.3 root 963: /*
964:
965: * We have to use temps while allocating and freeing mem
966:
967: * and addr so the memory protection code won't walk this
968:
969: * process' memory list in the middle.
970:
971: */
972:
973: void *pmem, *paddr;
974:
975:
976:
1.1 root 977: /* copy over the old address mapping */
978:
979: for (i = 0; i < proc->num_reg; i++) {
980:
981: newmem[i] = proc->mem[i];
982:
983: newaddr[i] = proc->addr[i];
984:
985: if (newmem[i] == 0)
986:
987: assert(newaddr[i] == 0);
988:
989: }
990:
991: /* initialize the rest of the tables */
992:
993: for(; i < proc->num_reg + NUM_REGIONS; i++) {
994:
995: newmem[i] = 0;
996:
997: newaddr[i] = 0;
998:
999: }
1000:
1.1.1.3 root 1001: /* free the old tables (carefully! for memory protection) */
1002:
1003: pmem = proc->mem;
1.1 root 1004:
1.1.1.3 root 1005: paddr = proc->addr;
1006:
1007: proc->mem = NULL;
1008:
1009: proc->addr = NULL;
1010:
1011: kfree(pmem); kfree(paddr);
1.1 root 1012:
1013: proc->mem = newmem;
1014:
1015: proc->addr = newaddr;
1016:
1017: proc->num_reg += NUM_REGIONS;
1018:
1.1.1.3 root 1019: /* this time we will succeed */
1.1 root 1020:
1.1.1.3 root 1021: goto again;
1.1 root 1022:
1.1.1.3 root 1023: } else {
1.1 root 1024:
1.1.1.3 root 1025: if (newmem) kfree(newmem);
1.1 root 1026:
1.1.1.3 root 1027: if (newaddr) kfree(newaddr);
1.1 root 1028:
1.1.1.3 root 1029: DEBUG(("attach_region: failed"));
1.1 root 1030:
1.1.1.3 root 1031: return 0;
1.1 root 1032:
1.1.1.3 root 1033: }
1.1 root 1034:
1035: }
1036:
1037:
1038:
1039: /*
1040:
1041: * detach_region(proc, reg): remove region from the procedure's address
1042:
1043: * space. If no more processes reference the region, return it to the
1044:
1045: * system. Note that we search backwards, so that the most recent
1046:
1047: * attachment of memory gets detached!
1048:
1049: */
1050:
1051:
1052:
1053: void
1054:
1055: detach_region(proc, reg)
1056:
1057: PROC *proc;
1058:
1059: MEMREGION *reg;
1060:
1061: {
1062:
1063: int i;
1064:
1065:
1066:
1067: if (!reg) return;
1068:
1.1.1.3 root 1069:
1070:
1071: TRACELOW(("detach_region %lx len %lx from pid %d",
1072:
1073: reg->loc, reg->len, proc->pid));
1074:
1075:
1076:
1.1 root 1077: for (i = proc->num_reg - 1; i >= 0; i--) {
1078:
1079: if (proc->mem[i] == reg) {
1080:
1081: reg->links--;
1082:
1083: proc->mem[i] = 0; proc->addr[i] = 0;
1084:
1085: if (reg->links == 0) {
1086:
1087: free_region(reg);
1088:
1089: }
1090:
1.1.1.3 root 1091: else {
1092:
1093: /* cause curproc's table to be updated */
1094:
1.1.1.5 ! root 1095: mark_proc_region(proc,reg,PROT_I);
1.1.1.3 root 1096:
1097: }
1098:
1.1 root 1099: return;
1100:
1101: }
1102:
1103: }
1104:
1.1.1.2 root 1105: DEBUG(("detach_region: region not attached"));
1.1 root 1106:
1107: }
1108:
1109:
1110:
1111: /*
1112:
1.1.1.3 root 1113: * get_region(MMAP map, ulong size, int mode) -- allocate a new region of the
1.1 root 1114:
1115: * given size in the given memory map. if no region big enough is available,
1116:
1117: * return NULL, otherwise return a pointer to the region.
1118:
1.1.1.3 root 1119: * "mode" tells us about memory protection modes
1120:
1121: *
1122:
1.1 root 1123: * the "links" field in the region is set to 1
1124:
1125: *
1126:
1127: * BEWARE: new_region may call get_region (indirectly), so we have to be
1128:
1129: * _very_ careful with re-entrancy in this function
1130:
1131: */
1132:
1133:
1134:
1135: MEMREGION *
1136:
1.1.1.3 root 1137: get_region(map, size, mode)
1.1 root 1138:
1139: MMAP map;
1140:
1141: ulong size;
1142:
1.1.1.3 root 1143: int mode;
1144:
1.1 root 1145: {
1146:
1147: MEMREGION *m, *n;
1148:
1149:
1150:
1.1.1.3 root 1151: TRACELOW(("get_region(%s,%lx,%x)",
1152:
1153: (map == ker ? "ker" : (map == core ? "core" : "alt")),
1154:
1155: size, mode));
1156:
1157:
1158:
1.1 root 1159: /* precautionary measures */
1160:
1161: if (size == 0) {
1162:
1.1.1.2 root 1163: DEBUG(("request for 0 bytes??"));
1.1 root 1164:
1165: size = 1;
1166:
1167: }
1168:
1169:
1170:
1171: size = ROUND(size);
1172:
1173:
1174:
1175: n = *map;
1176:
1177:
1178:
1179: sanity_check(map);
1180:
1181: /* exact matches are likely to be rare, so we pre-allocate a new
1182:
1183: * region here; this helps us to avoid re-entrancy problems
1184:
1185: * when new_region calls get_region
1186:
1187: */
1188:
1189: m = new_region();
1190:
1191:
1192:
1193: while (n) {
1194:
1195: if (ISFREE(n)) {
1196:
1197: if (n->len == size) {
1198:
1199: if (m) dispose_region(m);
1200:
1201: n->links++;
1202:
1.1.1.3 root 1203: goto win;
1.1 root 1204:
1205: }
1206:
1207: else if (n->len > size) {
1208:
1209: /* split a new region, 'm', which will contain the free bytes after n */
1210:
1211: if (m) {
1212:
1213: m->next = n->next;
1214:
1215: n->next = m;
1216:
1217: m->mflags = n->mflags & M_MAP;
1218:
1219: m->loc = n->loc + size;
1220:
1221: m->len = n->len - size;
1222:
1223: n->len = size;
1224:
1225: n->links++;
1226:
1.1.1.3 root 1227: goto win;
1.1 root 1228:
1229: } else {
1230:
1.1.1.2 root 1231: DEBUG(("get_region: no regions left"));
1.1 root 1232:
1233: return 0;
1234:
1235: }
1236:
1237: }
1238:
1239: }
1240:
1241: n = n->next;
1242:
1243: }
1244:
1245:
1246:
1247: if (m)
1248:
1249: dispose_region(m);
1250:
1.1.1.3 root 1251:
1252:
1253: TRACELOW(("get_region: no memory left in this map"));
1254:
1.1 root 1255: return NULL;
1256:
1.1.1.3 root 1257:
1258:
1259: win:
1260:
1261: mark_region(n, mode & PROT_PROTMODE);
1262:
1263: if (mode & M_KEEP) n->mflags |= M_KEEP;
1264:
1265:
1266:
1267: return n;
1268:
1.1 root 1269: }
1270:
1271:
1272:
1273: /*
1274:
1275: * free_region(MEMREGION *reg): free the indicated region. The map
1276:
1277: * in which the region is contained is given by reg->mflags.
1278:
1279: * the caller is responsible for making sure that the region
1280:
1281: * really should be freed, i.e. that reg->links == 0.
1282:
1.1.1.2 root 1283: *
1284:
1285: * special things to do:
1286:
1287: * if the region is a shared text region, we must close the
1288:
1289: * associated file descriptor
1290:
1.1 root 1291: */
1292:
1293:
1294:
1295: void
1296:
1297: free_region(reg)
1298:
1299: MEMREGION *reg;
1300:
1301: {
1302:
1303: MMAP map;
1304:
1305: MEMREGION *m;
1306:
1.1.1.2 root 1307: SHTEXT *s, **old;
1308:
1.1 root 1309:
1310:
1311: if (!reg) return;
1312:
1313:
1314:
1315: assert(ISFREE(reg));
1316:
1317:
1318:
1.1.1.2 root 1319: if (reg->mflags & M_SHTEXT) {
1320:
1321: TRACE(("freeing shared text region"));
1322:
1323: old = &text_reg;
1324:
1325: for(;;) {
1326:
1327: s = *old;
1328:
1329: if (!s) break;
1330:
1331: if (s->text == reg) {
1332:
1.1.1.3 root 1333: if (s->f)
1334:
1335: do_close(s->f);
1.1.1.2 root 1336:
1337: *old = s->next;
1338:
1339: kfree(s);
1340:
1341: break;
1342:
1343: }
1344:
1345: old = &s->next;
1346:
1347: }
1348:
1349: if (!s) {
1350:
1351: DEBUG(("No shared text entry for M_SHTEXT region??"));
1352:
1353: }
1354:
1355: }
1356:
1357:
1358:
1.1 root 1359: if (reg->mflags & M_CORE)
1360:
1361: map = core;
1362:
1363: else if (reg->mflags & M_ALT)
1364:
1365: map = alt;
1366:
1367: else if (reg->mflags & M_KER)
1368:
1369: map = ker;
1370:
1371: else {
1372:
1373: FATAL("free_region: region flags not valid (%x)", reg->mflags);
1374:
1375: }
1376:
1377: reg->mflags &= M_MAP;
1378:
1379:
1380:
1.1.1.3 root 1381: /* unhook any vectors pointing into this region */
1382:
1383: unlink_vectors(reg->loc, reg->loc + reg->len);
1.1 root 1384:
1385:
1.1.1.3 root 1386:
1387: /* BUG(?): should invalidate caches entries - a copyback cache could stuff
1.1.1.2 root 1388:
1389: * things into freed memory.
1390:
1.1.1.3 root 1391: * cinv(reg->loc, reg->len);
1.1.1.2 root 1392:
1393: */
1394:
1.1.1.3 root 1395: m = *map;
1396:
1397: assert(m);
1398:
1399:
1400:
1401: /* MEMPROT: invalidate */
1402:
1403: if (map == core || map == alt)
1404:
1405: mark_region(reg,PROT_I);
1406:
1407:
1408:
1.1 root 1409: if (m == reg) goto merge_after;
1410:
1411:
1412:
1413: /* merge previous region if it's free and contiguous with 'reg' */
1414:
1415:
1416:
1417: /* first, we find the region */
1418:
1419: while (m && m->next != reg)
1420:
1421: m = m->next;
1422:
1423:
1424:
1.1.1.2 root 1425: if (m == NULL) {
1426:
1427: FATAL("couldn't find region %lx: loc: %lx len: %ld",
1428:
1429: reg, reg->loc, reg->len);
1430:
1431: }
1.1 root 1432:
1433:
1434:
1435: if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
1436:
1437: m->len += reg->len;
1438:
1439: assert(m->next == reg);
1440:
1441: m->next = reg->next;
1442:
1443: reg->next = 0;
1444:
1445: dispose_region(reg);
1446:
1447: reg = m;
1448:
1449: }
1450:
1451:
1452:
1453: /* merge next region if it's free and contiguous with 'reg' */
1454:
1455: merge_after:
1456:
1457: m = reg->next;
1458:
1459: if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
1460:
1461: reg->len += m->len;
1462:
1463: reg->next = m->next;
1464:
1465: m->next = 0;
1466:
1467: dispose_region(m);
1468:
1469: }
1470:
1471:
1472:
1473: sanity_check(map);
1474:
1475: }
1476:
1477:
1478:
1479: /*
1480:
1481: * shrink_region(MEMREGION *reg, ulong newsize):
1482:
1483: * shrink region 'reg', so that it is now 'newsize' bytes long.
1484:
1485: * if 'newsize' is bigger than the region's current size, return EGSBF;
1486:
1487: * otherwise return 0.
1488:
1489: */
1490:
1491:
1492:
1493: long
1494:
1495: shrink_region(reg, newsize)
1496:
1497: MEMREGION *reg;
1498:
1499: ulong newsize;
1500:
1501: {
1502:
1503: MEMREGION *n;
1504:
1505: ulong diff;
1506:
1507:
1508:
1509:
1510:
1511: newsize = ROUND(newsize);
1512:
1513:
1514:
1515: assert(reg->links > 0);
1516:
1517:
1518:
1.1.1.2 root 1519: if (!(reg->mflags & (M_CORE | M_ALT | M_KER))) {
1.1 root 1520:
1521: FATAL("shrink_region: bad region flags (%x)", reg->mflags);
1522:
1523: }
1524:
1525:
1526:
1527: /* shrinking to 0 is the same as freeing */
1528:
1529: if (newsize == 0) {
1530:
1531: detach_region(curproc, reg);
1532:
1533: return 0;
1534:
1535: }
1536:
1537:
1538:
1539: /* if new size is the same as old size, don't do anything */
1540:
1541: if (newsize == reg->len) {
1542:
1543: return 0; /* nothing to do */
1544:
1545: }
1546:
1547:
1548:
1549: if (newsize > reg->len) {
1550:
1.1.1.2 root 1551: DEBUG(("shrink_region: request to make region bigger"));
1.1 root 1552:
1553: return EGSBF; /* growth failure */
1554:
1555: }
1556:
1557:
1558:
1559: /* OK, we're going to free (reg->len - newsize) bytes at the end of
1560:
1561: this block. If the block after us is already free, simply add the
1562:
1563: space to that block.
1564:
1565: */
1566:
1567: n = reg->next;
1568:
1569: diff = reg->len - newsize;
1570:
1571:
1572:
1573: if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
1574:
1575: reg->len = newsize;
1576:
1577: n->loc -= diff;
1578:
1579: n->len += diff;
1580:
1.1.1.3 root 1581: /* MEMPROT: invalidate the second half */
1582:
1583: /* (part of it is already invalid; that's OK) */
1584:
1585: mark_region(n,PROT_I);
1586:
1587:
1588:
1.1 root 1589: return 0;
1590:
1591: }
1592:
1593: else {
1594:
1595: n = new_region();
1596:
1597: if (!n) {
1598:
1.1.1.2 root 1599: DEBUG(("shrink_region: new_region failed"));
1.1 root 1600:
1601: return EINTRN;
1602:
1603: }
1604:
1605: reg->len = newsize;
1606:
1607: n->loc = reg->loc + newsize;
1608:
1609: n->len = diff;
1610:
1611: n->mflags = reg->mflags & M_MAP;
1612:
1613: n->next = reg->next;
1614:
1615: reg->next = n;
1616:
1.1.1.3 root 1617: /* MEMPROT: invalidate the new, free region */
1618:
1619: mark_region(n,PROT_I);
1620:
1.1 root 1621: }
1622:
1623: return 0;
1624:
1625: }
1626:
1627:
1628:
1629: /*
1630:
1631: * max_rsize(map): return the length of the biggest free region
1632:
1633: * in the given memory map, or 0 if no regions remain.
1634:
1635: */
1636:
1637:
1638:
1639: long
1640:
1641: max_rsize(map)
1642:
1643: MMAP map;
1644:
1645: {
1646:
1.1.1.2 root 1647: MEMREGION *m;
1.1 root 1648:
1649: long size = 0;
1650:
1651:
1652:
1653: for (m = *map; m; m = m->next) {
1654:
1655: if (ISFREE(m)) {
1656:
1657: if (m->len > size) {
1658:
1659: size = m->len;
1660:
1661: }
1662:
1663: }
1664:
1665: }
1666:
1667: return size;
1668:
1669: }
1670:
1671:
1672:
1673: /*
1674:
1675: * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
1676:
1677: * the given memory map; if flag == 0, return only the number of free
1678:
1679: * bytes
1680:
1681: */
1682:
1683:
1684:
1685: long
1686:
1687: tot_rsize(map, flag)
1688:
1689: MMAP map;
1690:
1691: int flag;
1692:
1693: {
1694:
1695: MEMREGION *m;
1696:
1697: long size = 0;
1698:
1699:
1700:
1701: for (m = *map; m; m = m->next) {
1702:
1703: if (flag || ISFREE(m)) {
1704:
1705: size += m->len;
1706:
1707: }
1708:
1709: }
1710:
1711: return size;
1712:
1713: }
1714:
1715:
1716:
1717: /*
1718:
1.1.1.3 root 1719: * alloc_region(MMAP map, ulong size, int mode): allocate a new region and
1.1 root 1720:
1.1.1.3 root 1721: * attach it to the current process; returns the address at which the region
1.1 root 1722:
1.1.1.3 root 1723: * was attached, or NULL. The mode argument is the memory protection mode to
1.1 root 1724:
1.1.1.3 root 1725: * give to get_region, and in turn to mark_region.
1.1 root 1726:
1727: */
1728:
1729:
1730:
1731: virtaddr
1732:
1.1.1.3 root 1733: alloc_region(map, size, mode)
1.1 root 1734:
1735: MMAP map;
1736:
1737: ulong size;
1738:
1.1.1.3 root 1739: int mode;
1740:
1.1 root 1741: {
1742:
1743: MEMREGION *m;
1744:
1745: PROC *proc = curproc;
1746:
1747: virtaddr v;
1748:
1749:
1750:
1.1.1.3 root 1751: TRACELOW(("alloc_region(map,size: %lx,mode: %x)",size,mode));
1752:
1753: if (!size) {
1754:
1755: DEBUG(("alloc_region of zero bytes?!"));
1756:
1757: return 0;
1758:
1759: }
1760:
1761:
1762:
1763: m = get_region(map, size, mode);
1.1 root 1764:
1765: if (!m) {
1766:
1.1.1.3 root 1767: TRACELOW(("alloc_region: get_region failed"));
1768:
1.1 root 1769: return 0;
1770:
1771: }
1772:
1773:
1774:
1.1.1.2 root 1775: /* sanity check: even addresses only, please */
1776:
1777: assert((m->loc & MASKBITS) == 0);
1778:
1779:
1780:
1.1 root 1781: v = attach_region(proc, m);
1782:
1783: /* NOTE: get_region returns a region with link count 1; since attach_region
1784:
1785: * increments the link count, we restore it after calling attach_region
1786:
1787: */
1788:
1789: m->links = 1;
1790:
1791: if (!v) {
1792:
1793: m->links = 0;
1794:
1795: free_region(m);
1796:
1.1.1.3 root 1797: TRACE(("alloc_region: attach_region failed"));
1798:
1.1 root 1799: return 0;
1800:
1801: }
1802:
1803: return v;
1804:
1805: }
1806:
1807:
1808:
1809: /*
1810:
1811: * routines for creating a copy of an environment, and a new basepage.
1812:
1813: * note that the memory regions created should immediately be attached to
1814:
1815: * a process! Also note that create_env always operates in ST RAM, but
1816:
1817: * create_base might not.
1818:
1819: */
1820:
1821:
1822:
1823: MEMREGION *
1824:
1.1.1.4 root 1825: create_env(env, flags)
1.1 root 1826:
1827: const char *env;
1828:
1.1.1.4 root 1829: ulong flags;
1830:
1.1 root 1831: {
1832:
1833: long size;
1834:
1835: MEMREGION *m;
1836:
1837: virtaddr v;
1838:
1839: const char *old;
1840:
1841: char *new;
1842:
1.1.1.4 root 1843: short protmode;
1844:
1.1.1.3 root 1845:
1.1 root 1846:
1847: if (!env) {
1848:
1849: env = ((BASEPAGE *)curproc->base)->p_env;
1850:
1851: /* duplicate parent's environment */
1852:
1853: }
1854:
1855: size = 2;
1856:
1857: old = env;
1858:
1859: while (*env || *(env+1))
1860:
1861: env++,size++;
1862:
1.1.1.3 root 1863:
1864:
1.1.1.4 root 1865: protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
1866:
1867:
1868:
1869: v = alloc_region(core, size, protmode);
1.1.1.3 root 1870:
1871: /* if core fails, try alt */
1872:
1873: if (!v)
1874:
1.1.1.4 root 1875: v = alloc_region(alt, size, protmode);
1.1.1.3 root 1876:
1877:
1.1 root 1878:
1879: if (!v) {
1880:
1.1.1.2 root 1881: DEBUG(("create_env: alloc_region failed"));
1.1 root 1882:
1883: return (MEMREGION *)0;
1884:
1885: }
1886:
1887: m = addr2mem(v);
1888:
1889:
1890:
1891: /* copy the old environment into the new */
1892:
1893: new = (char *) m->loc;
1894:
1.1.1.3 root 1895: TRACE(("copying environment: from %lx to %lx", old, new));
1896:
1.1 root 1897: while (size > 0) {
1898:
1899: *new++ = *old++;
1900:
1901: --size;
1902:
1903: }
1904:
1.1.1.3 root 1905: TRACE(("finished copying environment"));
1906:
1907:
1908:
1.1 root 1909: return m;
1910:
1911: }
1912:
1913:
1914:
1915: MEMREGION *
1916:
1917: create_base(cmd, env, flags, prgsize)
1918:
1919: const char *cmd;
1920:
1921: MEMREGION *env;
1922:
1923: ulong flags, prgsize;
1924:
1925: {
1926:
1927: long len, coresize, altsize;
1928:
1929: MMAP map;
1930:
1931: MEMREGION *m;
1932:
1933: BASEPAGE *b;
1934:
1.1.1.3 root 1935: short protmode;
1936:
1.1 root 1937:
1938:
1939: /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
1940:
1941: RAM if enough is available. "enough" is: if more alt ram than ST ram,
1942:
1943: load there; otherwise, if more than (minalt+1)*128K alt ram available
1944:
1945: for heap space, load in alt ram ("minalt" is the high byte of flags)
1946:
1947: */
1948:
1949: if (flags & F_ALTLOAD) {
1950:
1951: coresize = max_rsize(core);
1952:
1953: altsize = max_rsize(alt);
1954:
1955: if (altsize >= coresize)
1956:
1957: map = alt;
1958:
1959: else {
1960:
1.1.1.2 root 1961: len = (flags & F_MINALT) >> 28L;
1.1 root 1962:
1963: len = (len+1)*128*1024L + prgsize + 256;
1964:
1965: if (altsize >= len)
1966:
1967: map = alt;
1968:
1969: else
1970:
1971: map = core;
1972:
1973: }
1974:
1975: }
1976:
1977: else
1978:
1979: map = core;
1980:
1981:
1982:
1983: len = max_rsize(map);
1984:
1.1.1.5 ! root 1985: if (curproc->maxmem && len > curproc->maxmem) {
! 1986:
! 1987: len = curproc->maxmem;
! 1988:
! 1989: }
! 1990:
! 1991:
! 1992:
1.1.1.3 root 1993: if (len < prgsize) {
1994:
1995: /* can't possibly load this file in its eligible regions */
1996:
1997: DEBUG(("create_base: max_rsize smaller than prgsize"));
1998:
1999: return 0;
2000:
2001: }
2002:
1.1 root 2003:
2004:
2005: /* make sure that a little bit of memory is left over */
2006:
2007: if (len > 2*KEEP_MEM) {
2008:
2009: len -= KEEP_MEM;
2010:
2011: }
2012:
1.1.1.3 root 2013:
2014:
2015: protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
2016:
2017:
2018:
2019: m = addr2mem(alloc_region(map, len, protmode));
1.1 root 2020:
2021: if (!m) {
2022:
1.1.1.2 root 2023: DEBUG(("create_base: alloc_region failed"));
1.1 root 2024:
2025: return 0;
2026:
2027: }
2028:
2029: b = (BASEPAGE *)(m->loc);
2030:
2031:
2032:
2033: zero((char *)b, (long)sizeof(BASEPAGE));
2034:
2035: b->p_lowtpa = (long)b;
2036:
2037: b->p_hitpa = m->loc + m->len;
2038:
2039: b->p_env = (char *)env->loc;
2040:
2041: b->p_flags = flags;
2042:
2043:
2044:
2045: if (cmd)
2046:
2047: strncpy(b->p_cmdlin, cmd, 126);
2048:
2049: return m;
2050:
2051: }
2052:
2053:
2054:
2055: /*
2056:
1.1.1.2 root 2057: * load_region(): loads the program with the given file name
1.1 root 2058:
1.1.1.2 root 2059: * into a new region, and returns a pointer to that region. On
1.1 root 2060:
1.1.1.2 root 2061: * an error, returns 0 and leaves the error number in mint_errno.
1.1 root 2062:
1.1.1.2 root 2063: * "env" points to an already set up environment region, as returned
1.1 root 2064:
1.1.1.3 root 2065: * by create_env. On success, "xp" points to the file attributes, which
2066:
2067: * Pexec has already determined, and "fp" points to the programs
1.1 root 2068:
1.1.1.3 root 2069: * prgflags. "text" is a pointer to a MEMREGION
1.1 root 2070:
1.1.1.2 root 2071: * pointer, which will be set to the region occupied by the shared
1.1 root 2072:
1.1.1.2 root 2073: * text segment of this program (if applicable).
1.1 root 2074:
1.1.1.2 root 2075: */
1.1 root 2076:
2077:
2078:
2079: MEMREGION *
2080:
1.1.1.3 root 2081: load_region(filename, env, cmdlin, xp, text, fp)
1.1 root 2082:
2083: const char *filename;
2084:
2085: MEMREGION *env;
2086:
2087: const char *cmdlin;
2088:
2089: XATTR *xp; /* attributes for the file just loaded */
2090:
1.1.1.2 root 2091: MEMREGION **text; /* set to point to shared text region,
2092:
2093: if any */
2094:
1.1.1.3 root 2095: long *fp; /* prgflags for this file */
2096:
1.1 root 2097: {
2098:
2099: FILEPTR *f;
2100:
2101: DEVDRV *dev;
2102:
1.1.1.2 root 2103: MEMREGION *reg, *shtext;
1.1 root 2104:
2105: BASEPAGE *b;
2106:
1.1.1.2 root 2107: long size, start;
1.1 root 2108:
1.1.1.2 root 2109: FILEHEAD fh;
1.1 root 2110:
2111:
2112:
1.1.1.2 root 2113: /* bug: this should be O_DENYW mode, not O_DENYNONE */
1.1 root 2114:
1.1.1.2 root 2115: /* we must use O_DENYNONE because of the desktop and because of the
1.1 root 2116:
1.1.1.2 root 2117: * TOS file system brain-damage
1.1 root 2118:
1.1.1.2 root 2119: */
1.1 root 2120:
2121: f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
2122:
2123: if (!f) {
2124:
2125: return 0; /* mint_errno set by do_open */
2126:
2127: }
2128:
2129:
2130:
1.1.1.2 root 2131: dev = f->dev;
1.1 root 2132:
1.1.1.2 root 2133: size = (*dev->read)(f, (void *)&fh, (long)sizeof(fh));
1.1 root 2134:
1.1.1.2 root 2135: if (fh.fmagic != GEMDOS_MAGIC || size != (long)sizeof(fh)) {
1.1 root 2136:
1.1.1.2 root 2137: DEBUG(("load_region: file not executable"));
1.1 root 2138:
2139: mint_errno = ENOEXEC;
2140:
2141: failed:
2142:
2143: do_close(f);
2144:
2145: return 0;
2146:
2147: }
2148:
2149:
2150:
1.1.1.5 ! root 2151: if (((fh.flag & F_PROTMODE) >> F_PROTSHIFT) > PROT_MAX_MODE) {
! 2152:
! 2153: DEBUG (("load_region: invalid protection mode changed to private"));
! 2154:
! 2155: fh.flag = (fh.flag & ~F_PROTMODE) | F_PROT_P;
! 2156:
! 2157: }
! 2158:
1.1.1.3 root 2159: *fp = fh.flag;
2160:
2161:
2162:
1.1.1.2 root 2163: if (fh.flag & F_SHTEXT) {
2164:
2165: TRACE(("loading shared text segment"));
2166:
2167: shtext = get_text_seg(f, &fh, xp);
2168:
2169: if (!shtext) {
2170:
2171: DEBUG(("load_region: unable to get shared text segment"));
2172:
2173: /* mint_errno set in get_text_seg */
2174:
2175: goto failed;
2176:
2177: }
2178:
2179: size = fh.fdata + fh.fbss;
2180:
2181: } else {
2182:
2183: size = fh.ftext + fh.fdata + fh.fbss;
2184:
2185: shtext = 0;
2186:
2187: }
2188:
2189:
1.1 root 2190:
1.1.1.3 root 2191: reg = create_base(cmdlin, env, fh.flag, size);
1.1 root 2192:
1.1.1.3 root 2193: if (reg && size+1024L > reg->len) {
1.1 root 2194:
1.1.1.3 root 2195: DEBUG(("load_region: insufficient memory to load"));
1.1 root 2196:
1.1.1.3 root 2197: detach_region(curproc, reg);
1.1 root 2198:
1.1.1.3 root 2199: reg = 0;
1.1 root 2200:
2201: }
2202:
2203:
2204:
2205: if (reg == 0) {
2206:
1.1.1.2 root 2207: if (shtext) {
2208:
2209: detach_region(curproc, shtext);
2210:
2211: }
2212:
1.1 root 2213: mint_errno = ENSMEM;
2214:
2215: goto failed;
2216:
2217: }
2218:
2219:
2220:
2221: b = (BASEPAGE *)reg->loc;
2222:
2223: b->p_flags = fh.flag;
2224:
1.1.1.2 root 2225: if (shtext) {
2226:
2227: b->p_tbase = shtext->loc;
1.1 root 2228:
1.1.1.2 root 2229: b->p_tlen = 0;
1.1 root 2230:
1.1.1.2 root 2231: b->p_dbase = b->p_lowtpa + 256;
2232:
2233: } else {
2234:
2235: b->p_tbase = b->p_lowtpa + 256;
2236:
2237: b->p_tlen = fh.ftext;
2238:
2239: b->p_dbase = b->p_tbase + b->p_tlen;
2240:
2241: }
1.1 root 2242:
2243: b->p_dlen = fh.fdata;
2244:
2245: b->p_bbase = b->p_dbase + b->p_dlen;
2246:
1.1.1.2 root 2247: b->p_blen = fh.fbss;
1.1 root 2248:
2249:
2250:
1.1.1.2 root 2251: /* if shared text, then we start loading at the end of the
1.1 root 2252:
1.1.1.2 root 2253: * text region, since that is already set up
2254:
2255: */
2256:
2257: if (shtext) {
2258:
2259: /* skip over text info */
2260:
2261: size = fh.fdata;
2262:
2263: start = fh.ftext;
2264:
2265: } else {
2266:
2267: size = fh.ftext + fh.fdata;
2268:
2269: start = 0;
2270:
2271: }
2272:
2273:
2274:
2275: mint_errno = (int)load_and_reloc(f, &fh, (char *)b+256, start,
2276:
2277: size, b);
2278:
2279:
2280:
2281: if (mint_errno) {
1.1 root 2282:
2283: detach_region(curproc, reg);
2284:
1.1.1.2 root 2285: if (shtext) detach_region(curproc, shtext);
2286:
1.1 root 2287: goto failed;
2288:
2289: }
2290:
2291:
2292:
2293: if (fh.flag & F_FASTLOAD) /* fastload bit */
2294:
2295: size = b->p_blen;
2296:
2297: else
2298:
2299: size = b->p_hitpa - b->p_bbase;
2300:
1.1.1.5 ! root 2301: if (size > 0) {
! 2302:
! 2303: start = b->p_bbase;
! 2304:
! 2305: if (start & 1) {
! 2306:
! 2307: *(char *)start = 0;
! 2308:
! 2309: start++;
! 2310:
! 2311: --size;
! 2312:
! 2313: }
! 2314:
! 2315: zero((char *)start, size);
! 2316:
! 2317: }
1.1 root 2318:
2319:
2320:
1.1.1.2 root 2321: do_close(f);
1.1 root 2322:
1.1.1.2 root 2323: *text = shtext;
1.1 root 2324:
1.1.1.2 root 2325: return reg;
1.1 root 2326:
1.1.1.2 root 2327: }
2328:
2329:
2330:
2331: /*
2332:
2333: * load_and_reloc(f, fh, where, start, nbytes): load and relocate from
2334:
2335: * the open GEMDOS executable file f "nbytes" bytes starting at offset
2336:
2337: * "start" (relative to the end of the file header, i.e. from the first
2338:
2339: * byte of the actual program image in the file). "where" is the address
2340:
2341: * in (physical) memory into which the loaded image must be placed; it is
2342:
2343: * assumed that "where" is big enough to hold "nbytes" bytes!
1.1 root 2344:
2345: */
2346:
2347:
2348:
1.1.1.2 root 2349: long
2350:
2351: load_and_reloc(f, fh, where, start, nbytes, base)
2352:
2353: FILEPTR *f;
2354:
2355: FILEHEAD *fh;
2356:
2357: char *where;
2358:
2359: long start;
2360:
2361: long nbytes;
2362:
2363: BASEPAGE *base;
2364:
2365: {
2366:
2367: unsigned char c, *next;
2368:
2369: long r;
2370:
2371: DEVDRV *dev;
2372:
2373: #define LRBUFSIZ 8196
2374:
2375: static unsigned char buffer[LRBUFSIZ];
2376:
2377: long fixup, size, bytes_read;
2378:
2379: long reloc;
2380:
2381:
2382:
2383:
2384:
2385: TRACE(("load_and_reloc: %ld to %ld at %lx", start, nbytes+start, where));
2386:
2387: dev = f->dev;
2388:
2389:
2390:
2391: r = (*dev->lseek)(f, start+sizeof(FILEHEAD), SEEK_SET);
2392:
2393: if (r < 0) return r;
2394:
2395: r = (*dev->read)(f, where, nbytes);
2396:
2397: if (r != nbytes) {
2398:
2399: DEBUG(("load_region: unexpected EOF"));
2400:
2401: return ENOEXEC;
2402:
2403: }
2404:
2405:
2406:
2407: /* now do the relocation */
2408:
2409: /* skip over symbol table, etc. */
2410:
2411: r = (*dev->lseek)(f, sizeof(FILEHEAD) + fh->ftext + fh->fdata +
2412:
2413: fh->fsym, SEEK_SET);
2414:
2415: if (r < 0) return ENOEXEC;
2416:
2417:
2418:
2419: if (fh->reloc != 0 || (*dev->read)(f, (char *)&fixup, 4L) != 4L
2420:
2421: || fixup == 0) {
2422:
2423: return 0; /* no relocation to be performed */
2424:
2425: }
2426:
2427:
2428:
2429: size = LRBUFSIZ;
2430:
2431: bytes_read = 0;
2432:
2433: next = buffer;
2434:
1.1 root 2435:
2436:
1.1.1.2 root 2437: do {
2438:
2439: if (fixup >= nbytes + start) {
2440:
2441: TRACE(("load_region: end of relocation at %ld", fixup));
2442:
2443: break;
2444:
2445: }
2446:
2447: else if (fixup >= start) {
1.1 root 2448:
1.1.1.2 root 2449: reloc = *((long *)(where + fixup - start));
2450:
2451: if (reloc < fh->ftext) {
2452:
2453: reloc += base->p_tbase;
2454:
2455: } else if (reloc < fh->ftext + fh->fdata && base->p_dbase) {
2456:
2457: reloc += base->p_dbase - fh->ftext;
2458:
2459: } else if (reloc < fh->ftext + fh->fdata + fh->fbss && base->p_bbase) {
2460:
2461: reloc += base->p_bbase - (fh->ftext + fh->fdata);
2462:
2463: } else {
2464:
2465: DEBUG(("load_region: bad relocation: %ld", reloc));
2466:
2467: if (base->p_dbase)
2468:
2469: reloc += base->p_dbase - fh->ftext; /* assume data reloc */
2470:
2471: else if (base->p_bbase)
2472:
2473: reloc += base->p_bbase - (fh->ftext + fh->fdata);
2474:
2475: else
2476:
2477: return ENOEXEC;
2478:
2479: }
2480:
2481: *((long *)(where + fixup - start)) = reloc;
2482:
2483: }
1.1 root 2484:
2485: do {
2486:
1.1.1.2 root 2487: if (!bytes_read) {
1.1 root 2488:
1.1.1.2 root 2489: bytes_read =
1.1 root 2490:
1.1.1.2 root 2491: (*dev->read)(f,(char *)buffer,size);
2492:
2493: next = buffer;
1.1 root 2494:
2495: }
2496:
1.1.1.2 root 2497: if (bytes_read < 0) {
1.1 root 2498:
1.1.1.2 root 2499: DEBUG(("load_region: EOF in relocation"));
1.1 root 2500:
1.1.1.2 root 2501: return ENOEXEC;
1.1 root 2502:
1.1.1.2 root 2503: }
1.1 root 2504:
1.1.1.2 root 2505: else if (bytes_read == 0)
1.1 root 2506:
1.1.1.2 root 2507: c = 0;
1.1 root 2508:
1.1.1.2 root 2509: else {
1.1 root 2510:
1.1.1.2 root 2511: c = *next++; bytes_read--;
1.1 root 2512:
1.1.1.2 root 2513: }
1.1 root 2514:
1.1.1.2 root 2515: if (c == 1) fixup += 254;
1.1 root 2516:
1.1.1.2 root 2517: } while (c == 1);
1.1 root 2518:
1.1.1.2 root 2519: fixup += ( (unsigned) c) & 0xff;
1.1 root 2520:
1.1.1.2 root 2521: } while (c);
1.1 root 2522:
2523:
2524:
1.1.1.2 root 2525: return 0;
1.1 root 2526:
1.1.1.2 root 2527: }
2528:
2529:
2530:
2531: /*
2532:
2533: * function to check for existence of a shared text region
2534:
2535: * corresponding to file "f", and if none is found, to create one
2536:
2537: * the memory region being returned is attached to the current
2538:
2539: * process
2540:
2541: */
2542:
2543:
2544:
2545: MEMREGION *
2546:
2547: get_text_seg(f, fh, xp)
2548:
2549: FILEPTR *f;
2550:
2551: FILEHEAD *fh;
2552:
2553: XATTR *xp;
2554:
2555: {
2556:
2557: SHTEXT *s;
1.1 root 2558:
1.1.1.2 root 2559: MEMREGION *m;
2560:
2561: long r;
2562:
2563: BASEPAGE b;
2564:
2565:
2566:
2567: s = text_reg;
2568:
2569:
2570:
2571: while(s) {
2572:
1.1.1.3 root 2573: if (s->f && samefile(&f->fc, &s->f->fc) &&
1.1.1.2 root 2574:
2575: xp->mtime == s->mtime &&
2576:
2577: xp->mdate == s->mdate)
2578:
2579: {
1.1 root 2580:
1.1.1.2 root 2581: m = s->text;
1.1 root 2582:
1.1.1.2 root 2583: if (attach_region(curproc, m)) {
1.1 root 2584:
1.1.1.2 root 2585: TRACE(("re-using shared text region %lx", m));
2586:
2587: return m;
2588:
2589: }
2590:
2591: else {
2592:
2593: mint_errno = ENSMEM;
2594:
2595: return 0;
2596:
2597: }
2598:
2599: }
2600:
2601: s = s->next;
1.1 root 2602:
2603: }
2604:
2605:
2606:
1.1.1.2 root 2607: /* hmmm, not found; OK, we'll have to create a new text region */
2608:
2609:
2610:
2611: s = kmalloc(SIZEOF(SHTEXT));
2612:
2613: if (!s) {
2614:
2615: mint_errno = ENSMEM;
2616:
2617: return 0;
2618:
2619: }
2620:
2621: m = 0;
2622:
2623: /* actually, I can't see why loading in TT RAM is ever undesireable,
2624:
2625: * since shared text programs should be very clean (and since only
2626:
2627: * the text segment is going in there). But better safe than sorry.
2628:
2629: */
2630:
2631: if (fh->flag & F_ALTLOAD) {
2632:
1.1.1.3 root 2633: m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
1.1.1.2 root 2634:
2635: }
2636:
2637: if (!m)
2638:
1.1.1.3 root 2639: m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
1.1.1.2 root 2640:
2641:
2642:
2643: if (!m) {
2644:
2645: kfree(s);
2646:
2647: mint_errno = ENSMEM;
2648:
2649: return 0;
2650:
2651: }
2652:
2653:
2654:
2655: /* set up a fake "basepage" for load_and_reloc
2656:
2657: * note: the 0 values should make load_and_reloc
2658:
2659: * barf on any attempts at data relocation, since we have
2660:
2661: * no data segment
2662:
2663: */
2664:
2665: TRACE(("attempting to create shared text region"));
2666:
2667:
2668:
2669: b.p_tbase = m->loc;
2670:
2671: b.p_tlen = fh->ftext;
2672:
2673: b.p_dbase = 0;
2674:
2675: b.p_dlen = 0;
2676:
2677: b.p_bbase = b.p_blen = 0;
2678:
1.1 root 2679:
1.1.1.2 root 2680:
2681: r = load_and_reloc(f, fh, (char *)m->loc, 0, fh->ftext, &b);
2682:
2683: if (r) {
2684:
2685: detach_region(curproc, m);
2686:
2687: kfree(s);
2688:
2689: return 0;
2690:
2691: }
2692:
2693:
2694:
2695: /* region has valid shared text data */
2696:
2697: m->mflags |= M_SHTEXT;
2698:
2699:
2700:
2701: /*
2702:
2703: * KLUDGE: to make sure we always have up to date shared text
2704:
2705: * info, even across a network, we leave the file passed
2706:
2707: * to us open with DENYWRITE mode, so that nobody will
2708:
2709: * modify it.
2710:
2711: */
2712:
2713: f->links++; /* keep the file open longer */
2714:
2715:
2716:
2717: /* BUG: what if someone already has the file open for
2718:
2719: * writing? Then we could get screwed...
2720:
2721: */
2722:
2723: f->flags = (f->flags & ~O_SHMODE) | O_DENYW;
2724:
2725: s->f = f;
2726:
2727: s->text = m;
2728:
2729: s->next = text_reg;
2730:
2731: s->mtime = xp->mtime;
2732:
2733: s->mdate = xp->mdate;
2734:
2735: text_reg = s;
2736:
2737: TRACE(("shared text region %lx created", m));
2738:
2739: return m;
1.1 root 2740:
2741: }
2742:
2743:
2744:
2745: /*
2746:
2747: * exec_region(p, mem, thread): create a child process out of a mem region
2748:
2749: * "p" is the process structure set up by the parent; it may be "curproc",
2750:
2751: * if we're overlaying. "mem" is the loaded memory region returned by
2752:
2753: * "load region". Any open files (other than the standard handles) owned
2754:
2755: * by "p" are closed, and if thread !=0 all memory is released; the caller
2756:
2757: * must explicitly attach the environment and base region. The caller must
2758:
2759: * also put "p" on the appropriate queue (most likely READY_Q).
2760:
2761: */
2762:
2763:
2764:
2765: extern long mint_dos(), mint_bios();
2766:
2767:
2768:
2769: void rts() {} /* dummy termination routine */
2770:
2771:
2772:
2773: PROC *
2774:
2775: exec_region(p, mem, thread)
2776:
2777: PROC *p;
2778:
2779: MEMREGION *mem;
2780:
2781: int thread;
2782:
2783: {
2784:
2785: BASEPAGE *b;
2786:
2787: FILEPTR *f;
2788:
2789: int i;
2790:
2791: MEMREGION *m;
2792:
2793:
2794:
1.1.1.2 root 2795: TRACE(("exec_region"));
1.1 root 2796:
2797:
2798:
2799: b = (BASEPAGE *) mem->loc;
2800:
2801:
2802:
1.1.1.2 root 2803: cpush((void *)b->p_tbase, b->p_tlen); /* flush cached versions of the text */
2804:
2805:
2806:
1.1 root 2807: /* set some (undocumented) variables in the basepage */
2808:
2809: b->p_defdrv = p->curdrv;
2810:
2811: for (i = 0; i < 6; i++)
2812:
2813: b->p_devx[i] = i;
2814:
2815:
2816:
2817: p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
2818:
2819: p->base = b;
2820:
2821:
2822:
2823: /* close extra open files */
2824:
2825: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
2826:
1.1.1.2 root 2827: if ( (f = p->handle[i]) != 0 && (p->fdflags[i] & FD_CLOEXEC) ) {
1.1 root 2828:
2829: do_pclose(p, f);
2830:
2831: p->handle[i] = 0;
2832:
2833: }
2834:
2835: }
2836:
2837:
2838:
2839: /* initialize memory */
2840:
2841: recalc_maxmem(p);
2842:
2843: if (p->maxmem) {
2844:
2845: shrink_region(mem, p->maxmem);
2846:
2847: b->p_hitpa = b->p_lowtpa + mem->len;
2848:
2849: }
2850:
2851:
2852:
2853: p->memflags = b->p_flags;
2854:
2855:
2856:
2857: if (!thread) {
2858:
2859: for (i = 0; i < p->num_reg; i++) {
2860:
2861: m = p->mem[i];
2862:
2863: if (m) {
2864:
2865: m->links--;
2866:
2867: if (m->links <= 0)
2868:
2869: free_region(m);
2870:
2871: }
2872:
2873: }
2874:
2875: if (p->num_reg > NUM_REGIONS) {
2876:
1.1.1.3 root 2877: /*
2878:
2879: * If the proc struct has a larger mem array than
2880:
2881: * the default, then free it and allocate a
2882:
2883: * default-sized one.
2884:
2885: */
1.1 root 2886:
2887:
2888:
1.1.1.3 root 2889: /*
1.1 root 2890:
1.1.1.3 root 2891: * hoo ha! Memory protection problem here. Use
2892:
2893: * temps and pre-clear p->mem so memprot doesn't try
2894:
2895: * to walk these structures as we're freeing and
2896:
2897: * reallocating them! (Calling kmalloc can cause
2898:
2899: * a table walk if the alloc results in calling
2900:
2901: * get_region.)
2902:
2903: */
2904:
2905: void *pmem, *paddr;
2906:
2907:
2908:
2909: pmem = p->mem;
2910:
2911: paddr = p->addr;
2912:
2913: p->mem = NULL; p->addr = NULL;
2914:
2915: kfree(pmem); kfree(paddr);
2916:
2917:
2918:
2919: pmem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
2920:
2921: paddr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
2922:
2923: assert(pmem && paddr);
2924:
2925: p->mem = pmem;
2926:
2927: p->addr = paddr;
1.1 root 2928:
2929: p->num_reg = NUM_REGIONS;
2930:
2931: }
2932:
2933: zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
2934:
2935: zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
2936:
2937: }
2938:
2939:
2940:
2941: /* initialize signals */
2942:
2943: p->sigmask = 0;
2944:
2945: for (i = 0; i < NSIG; i++) {
2946:
2947: if (p->sighandle[i] != SIG_IGN) {
2948:
2949: p->sighandle[i] = SIG_DFL;
2950:
2951: p->sigflags[i] = 0;
2952:
2953: p->sigextra[i] = 0;
2954:
2955: }
2956:
2957: }
2958:
2959:
2960:
2961: /* zero the user registers, and set the FPU in a "clear" state */
2962:
2963: for (i = 0; i < 15; i++)
2964:
2965: p->ctxt[CURRENT].regs[i] = 0;
2966:
2967: p->ctxt[CURRENT].sr = 0;
2968:
2969: p->ctxt[CURRENT].fstate[0] = 0;
2970:
2971:
2972:
2973: /* set PC, stack registers, etc. appropriately */
2974:
2975: p->ctxt[CURRENT].pc = b->p_tbase;
2976:
2977:
2978:
2979: /* The "-0x20" is to make sure that syscall.s won't run past the end of
2980:
2981: * memory when the user makes a system call and doesn't push very many
2982:
2983: * parameters -- syscall always tries to copy the maximum possible number
2984:
2985: * of parms.
2986:
2987: *
2988:
2989: * NOTE: there's a sanity check here in case programs Mshrink a basepage
2990:
2991: * without fixing the p_hitpa field in the basepage; this is to ensure
2992:
2993: * compatibility with older versions of MiNT, which ignore p_hitpa.
2994:
2995: */
2996:
2997: if (valid_address(b->p_hitpa - 0x20))
2998:
2999: p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
3000:
3001: else
3002:
3003: p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
3004:
3005:
3006:
3007: p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
3008:
3009: p->ctxt[CURRENT].term_vec = (long)rts;
3010:
3011:
3012:
3013: /* set up stack for process */
3014:
3015: *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
3016:
3017:
3018:
3019: /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
3020:
3021: everything into the text region, including data; fork() must be careful
3022:
3023: to save the whole region, then. We assume that if the compiler (or
3024:
3025: assembler, or whatever) goes to the trouble of making separate text, data,
3026:
3027: and bss regions, then the text region is code and isn't modified and
3028:
3029: fork doesn't have to save it.
3030:
3031: */
3032:
1.1.1.2 root 3033: if (b->p_blen != 0 || b->p_dlen != 0)
1.1 root 3034:
3035: p->txtsize = b->p_tlen;
3036:
3037: else
3038:
3039: p->txtsize = 0;
3040:
3041:
3042:
3043: /*
3044:
3045: * An ugly hack: dLibs tries to poke around in the parent's address space
3046:
3047: * to find stuff. For now, we'll allow this by faking a pointer into
3048:
3049: * the parent's address space in the place in the basepage where dLibs is
3050:
3051: * expecting it. This ugly hack only works correctly if the Pexec'ing
3052:
3053: * program (i.e. curproc) is in user mode.
3054:
3055: */
3056:
1.1.1.2 root 3057: if (curproc != rootproc)
3058:
3059: curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
1.1 root 3060:
3061:
3062:
3063: return p;
3064:
3065: }
3066:
3067:
3068:
3069: /*
3070:
3071: * misc. utility routines
3072:
3073: */
3074:
3075:
3076:
3077: /*
3078:
3079: * long memused(p): return total memory allocated to process p
3080:
3081: */
3082:
3083:
3084:
3085: long
3086:
3087: memused(p)
3088:
3089: PROC *p;
3090:
3091: {
3092:
3093: int i;
3094:
3095: long size;
3096:
3097:
3098:
1.1.1.3 root 3099: /* a ZOMBIE owns no memory and its mem array ptr is zero */
3100:
3101: if (p->mem == NULL) return 0;
3102:
3103:
3104:
1.1 root 3105: size = 0;
3106:
3107: for (i = 0; i < p->num_reg; i++) {
3108:
3109: if (p->mem[i])
3110:
3111: size += p->mem[i]->len;
3112:
3113: }
3114:
3115: return size;
3116:
3117: }
3118:
3119:
3120:
3121: /*
3122:
3123: * recalculate the maximum memory limit on a process; this limit depends
3124:
3125: * on the max. allocated memory and max. total memory limits set by
3126:
3127: * p_setlimit (see dos.c), and (perhaps) on the size of the program
3128:
3129: * that the process is executing. whenever any of these things
3130:
3131: * change (through p_exec or p_setlimit) this routine must be called
3132:
3133: */
3134:
3135:
3136:
3137: void
3138:
3139: recalc_maxmem(p)
3140:
3141: PROC *p;
3142:
3143: {
3144:
3145: BASEPAGE *b;
3146:
3147: long siz;
3148:
3149:
3150:
3151: b = (BASEPAGE *)p->base;
3152:
3153: if (b)
3154:
3155: siz = b->p_tlen + b->p_dlen + b->p_blen;
3156:
3157: else
3158:
3159: siz = 0;
3160:
3161: p->maxmem = 0;
3162:
3163: if (p->maxdata) {
3164:
3165: p->maxmem = p->maxdata + siz;
3166:
3167: }
3168:
3169:
3170:
3171: if (p->maxcore) {
3172:
3173: if (p->maxmem == 0 || p->maxmem > p->maxcore)
3174:
3175: p->maxmem = p->maxcore;
3176:
3177: }
3178:
3179: if (p->maxmem && p->maxmem < siz)
3180:
3181: p->maxmem = siz;
3182:
3183: }
3184:
3185:
3186:
3187: /*
3188:
3189: * valid_address: checks to see if the indicated address falls within
3190:
3191: * memory attached to the current process
3192:
3193: */
3194:
3195:
3196:
3197: int
3198:
3199: valid_address(addr)
3200:
3201: long addr;
3202:
3203: {
3204:
3205: int i;
3206:
3207: MEMREGION *m;
3208:
3209:
3210:
3211: for (i = 0; i < curproc->num_reg; i++) {
3212:
3213: if ((m = curproc->mem[i]) != 0) {
3214:
3215: if (addr >= m->loc && addr <= m->loc + m->len)
3216:
3217: return 1;
3218:
3219: }
3220:
3221: }
3222:
3223: return 0;
3224:
3225: }
3226:
3227:
3228:
3229: /*
3230:
1.1.1.3 root 3231: * convert an address to a memory region; this works only in
3232:
3233: * the ST RAM and TT RAM maps, and will fail for memory that
3234:
3235: * MiNT doesn't own or which is virtualized
3236:
3237: */
3238:
3239:
3240:
3241: MEMREGION *
3242:
3243: addr2region(addr)
3244:
3245: long addr;
3246:
3247: {
3248:
3249: unsigned long ua = (unsigned long) addr;
3250:
3251:
3252:
3253: extern ulong mint_top_st, mint_top_tt;
3254:
3255: MEMREGION *r;
3256:
3257: MMAP map;
3258:
3259:
3260:
3261: if (ua < mint_top_st) {
3262:
3263: map = core;
3264:
3265: } else if (ua < mint_top_tt) {
3266:
3267: map = alt;
3268:
3269: } else {
3270:
3271: return 0;
3272:
3273: }
3274:
3275:
3276:
3277: for (r = *map; r; r = r->next) {
3278:
3279: if (addr >= r->loc && addr < r->loc + r->len)
3280:
3281: return r;
3282:
3283: }
3284:
3285: return 0;
3286:
3287: }
3288:
3289:
3290:
3291: /*
3292:
1.1 root 3293: * some debugging stuff
3294:
3295: */
3296:
3297:
3298:
3299: void
3300:
1.1.1.3 root 3301: DUMP_ALL_MEM()
3302:
3303: {
3304:
1.1.1.5 ! root 3305: #ifdef DEBUG_INFO
! 3306:
1.1.1.3 root 3307: DUMPMEM(ker);
3308:
3309: DUMPMEM(core);
3310:
3311: DUMPMEM(alt);
3312:
1.1.1.5 ! root 3313: FORCE("new memory region descriptor pages: %d", num_reg_requests);
! 3314:
! 3315: #endif
! 3316:
1.1.1.3 root 3317: }
3318:
3319:
3320:
3321: void
3322:
1.1 root 3323: DUMPMEM(map)
3324:
3325: MMAP map;
3326:
3327: {
3328:
1.1.1.4 root 3329: #ifdef DEBUG_INFO
1.1.1.2 root 3330:
1.1 root 3331: MEMREGION *m;
3332:
3333:
3334:
3335: m = *map;
3336:
1.1.1.3 root 3337: FORCE("%s memory dump: starting at region %lx",
3338:
3339: (map == ker ? "ker" : (map == core ? "core" : "alt")), m);
1.1 root 3340:
3341: while (m) {
3342:
1.1.1.3 root 3343: FORCE("%ld bytes at %lx (%d links); next region %lx", m->len, m->loc,
1.1 root 3344:
1.1.1.3 root 3345: m->links, m->next);
1.1 root 3346:
1.1.1.3 root 3347: m = m->next;
1.1 root 3348:
3349: }
3350:
1.1.1.4 root 3351: #else
3352:
3353: UNUSED(map);
3354:
1.1.1.2 root 3355: #endif
3356:
1.1 root 3357: }
3358:
3359:
3360:
3361: void
3362:
3363: sanity_check(map)
3364:
3365: MMAP map;
3366:
3367: {
3368:
3369: #ifdef SANITY_CHECK
3370:
3371: MEMREGION *m, *nxt;
3372:
3373: long end;
3374:
3375:
3376:
3377: m = *map;
3378:
3379: while (m) {
3380:
3381: nxt = m->next;
3382:
3383: if (nxt) {
3384:
3385: end = m->loc + m->len;
3386:
3387: if (m->loc < nxt->loc && end > nxt->loc) {
3388:
3389: FATAL("MEMORY CHAIN CORRUPTED");
3390:
3391: }
3392:
3393: else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
3394:
3395: ALERT("Continguous memory regions not merged!");
3396:
3397: }
3398:
3399: }
3400:
3401: m = nxt;
3402:
3403: }
3404:
1.1.1.2 root 3405: #else
3406:
3407: UNUSED(map);
3408:
1.1 root 3409: #endif
3410:
3411: }
3412:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.