9os

Experimental kernel using plan9 ideas for embedded device
git clone git://git.simple-cc.org/9os
Log | Files | Refs | README | LICENSE

map.c (2087B)


      1 #include <os9/os9.h>
      2 
      3 #include <libk.h>
      4 
      5 #include <string.h>
      6 
      7 Map *
      8 newstack(Task *tp)
      9 {
     10 	Map *mp = &tp->stack;
     11 
     12 	initref(&mp->ref);
     13 	mp->name = "stack";
     14 	mp->perm = MW |  MR;
     15 
     16 	mp->pa = -1;
     17 	mp->va = STACKADDR & (STACKADDR-1);
     18 	mp->siz = PAGESIZE;
     19 
     20 	if (mapseg(mp) < 0)
     21 		return NULL;
     22 
     23 	return mp;
     24 }
     25 
     26 Map *
     27 newkstack(Task *tp)
     28 {
     29 	Map *mp = &tp->kstack;
     30 
     31 	initref(&mp->ref);
     32 	mp->name = "kstack";
     33 	mp->perm = MW |  MR;
     34 
     35 	mp->pa = -1;
     36 	mp->va = KSTACKADDR & (STACKADDR-1);
     37 	mp->siz = PAGESIZE;
     38 
     39 	if (mapseg(mp) < 0)
     40 		return NULL;
     41 
     42 	return mp;
     43 }
     44 
     45 int
     46 unmapseg(Map *mp)
     47 {
     48 	Page *p;
     49 
     50 	dbg("unmap %s: %llx -> %llx\n",
     51 	    (mp->name) ? mp->name : "unnamed",
     52 	    mp->va, mp->pa);
     53 
     54 	for (p = mp->pages; p; p = p->next) {
     55 		vunmap(p->pa, p->va);
     56 		freep(p);
     57 	}
     58 
     59 	mp->pages = NULL;
     60 
     61 	return 0;
     62 }
     63 
     64 int
     65 mapseg(Map *mp)
     66 {
     67 	phyaddr_t pa;
     68 	uintptr_t va;
     69 	unsigned long i, n;
     70 	Page *p;
     71 
     72 	assert(mp->perm & MR);
     73 
     74 	dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n",
     75 		(mp->name) ? mp->name : "unnamed",
     76 		mp->va, mp->pa,
     77 		(mp->perm & MD) ? 'd' : 'n',
     78 		(mp->perm & MR) ? 'r' : '-',
     79 		(mp->perm & MW) ? 'w' : '-',
     80 		(mp->perm & MX) ? 'x' : '-',
     81 		mp->siz);
     82 
     83 	n =  (mp->siz + PAGESIZE-1)/PAGESIZE;
     84 	va = mp->va;
     85 	pa = mp->pa;
     86 
     87 	for (i = 0; i < n; i++) {
     88 		if (mp->pa == -1)
     89 			pa = -1;
     90 
     91 		if ((p = allocp(pa)) == NULL)
     92 			goto err;
     93 		p->va = va;
     94 		p->next = mp->pages;
     95 
     96 		if (vmap(p->pa, va, mp->perm) < 0) {
     97 			freep(p);
     98 			goto err;
     99 		}
    100 
    101 		mp->pages = p;
    102 		pa += PAGESIZE;
    103 		va += PAGESIZE;
    104 	}
    105 
    106 	return 0;
    107 
    108 err:
    109 	unmapseg(mp);
    110 	return -1;
    111 }
    112 
    113 void
    114 delmap(Map *mp)
    115 {
    116 	if (!decref(&mp->ref))
    117 		return;
    118 	unmapseg(mp);
    119 	freemap(mp);
    120 }
    121 
    122 Map *
    123 newmap(Map *from)
    124 {
    125 	Map *mp;
    126 	Page *pfrom, *pto;
    127 
    128 	if ((mp = allocmap()) == NULL)
    129 		return NULL;
    130 
    131 	*mp = *from;
    132 	mp->pages = NULL;
    133 	mp->next = NULL;
    134 	initref(&mp->ref);
    135 	mapseg(mp);
    136 
    137 	pto = mp->pages;
    138 	for (pfrom = from->pages; pfrom; pfrom = pfrom->next) {
    139 		assert(pfrom->va == pto->va);
    140 
    141 		vmap(pto->pa, (uintptr_t) bufto, MW);
    142 		vmap(pfrom->pa, (uintptr_t) buffrom, MR);
    143 
    144 		memcpy(bufto, buffrom, PAGESIZE);
    145 		barrier(DATA);
    146 
    147 		pto = pto->next;
    148 	}
    149 
    150 	return mp;
    151 }