xref: /minix3/minix/lib/libddekit/src/pgtab.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /*
2*433d6423SLionel Sambuc  * @author: Dirk Vogt
3*433d6423SLionel Sambuc  * @date 2010-02-10
4*433d6423SLionel Sambuc  *
5*433d6423SLionel Sambuc  * This file implements a local pagetable, to prevent IPC on physical
6*433d6423SLionel Sambuc  * address lookups. For now it's implement in a signle linked list.
7*433d6423SLionel Sambuc  *
8*433d6423SLionel Sambuc  * As soon as the DDE will use a premeptive thread mechanism access to
9*433d6423SLionel Sambuc  * the page table has to be sznchronized.
10*433d6423SLionel Sambuc  */
11*433d6423SLionel Sambuc #include "common.h"
12*433d6423SLionel Sambuc 
13*433d6423SLionel Sambuc #include <ddekit/pgtab.h>
14*433d6423SLionel Sambuc #include <ddekit/memory.h>
15*433d6423SLionel Sambuc #include <ddekit/lock.h>
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc #ifdef DDEBUG_LEVEL_PGTAB
18*433d6423SLionel Sambuc #undef DDEBUG
19*433d6423SLionel Sambuc #define DDEBUG DDEBUG_LEVEL_PGTAB
20*433d6423SLionel Sambuc #endif
21*433d6423SLionel Sambuc 
22*433d6423SLionel Sambuc #include "util.h"
23*433d6423SLionel Sambuc #include "debug.h"
24*433d6423SLionel Sambuc 
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc static void lock_pgtab(void);
27*433d6423SLionel Sambuc static void unlock_pgtab(void);
28*433d6423SLionel Sambuc static struct dde_pgtab_region * allocate_region(void);
29*433d6423SLionel Sambuc static void free_region(struct dde_pgtab_region *r);
30*433d6423SLionel Sambuc static void add_region(struct dde_pgtab_region *r);
31*433d6423SLionel Sambuc static void rm_region(struct dde_pgtab_region *r);
32*433d6423SLionel Sambuc static struct dde_pgtab_region * find_region_virt(ddekit_addr_t va);
33*433d6423SLionel Sambuc static struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa);
34*433d6423SLionel Sambuc 
35*433d6423SLionel Sambuc struct dde_pgtab_region {
36*433d6423SLionel Sambuc 	ddekit_addr_t vm_start;
37*433d6423SLionel Sambuc 	ddekit_addr_t phy_start;
38*433d6423SLionel Sambuc 	unsigned size;
39*433d6423SLionel Sambuc 	unsigned type; /* do we really have to keep track of the type here? */
40*433d6423SLionel Sambuc 	struct dde_pgtab_region *next;
41*433d6423SLionel Sambuc 	struct dde_pgtab_region *prev;
42*433d6423SLionel Sambuc };
43*433d6423SLionel Sambuc 
44*433d6423SLionel Sambuc static struct dde_pgtab_region  head = {0,0,0,0,&head,&head};
45*433d6423SLionel Sambuc static ddekit_lock_t lock;
46*433d6423SLionel Sambuc 
47*433d6423SLionel Sambuc /*
48*433d6423SLionel Sambuc  * INTERNAL HELPERS
49*433d6423SLionel Sambuc  */
50*433d6423SLionel Sambuc 
51*433d6423SLionel Sambuc /****************************************************************************/
52*433d6423SLionel Sambuc /*      lock_pgtab                                                          */
53*433d6423SLionel Sambuc /****************************************************************************/
lock_pgtab()54*433d6423SLionel Sambuc static void lock_pgtab()
55*433d6423SLionel Sambuc {
56*433d6423SLionel Sambuc 	ddekit_lock_lock(&lock);
57*433d6423SLionel Sambuc }
58*433d6423SLionel Sambuc 
59*433d6423SLionel Sambuc 
60*433d6423SLionel Sambuc /****************************************************************************/
61*433d6423SLionel Sambuc /*      unlock_pgtab                                                        */
62*433d6423SLionel Sambuc /****************************************************************************/
unlock_pgtab()63*433d6423SLionel Sambuc static void unlock_pgtab()
64*433d6423SLionel Sambuc {
65*433d6423SLionel Sambuc 	ddekit_lock_unlock(&lock);
66*433d6423SLionel Sambuc }
67*433d6423SLionel Sambuc 
68*433d6423SLionel Sambuc /****************************************************************************/
69*433d6423SLionel Sambuc /*      dde_pgtab_region                                                    */
70*433d6423SLionel Sambuc /****************************************************************************/
allocate_region()71*433d6423SLionel Sambuc static struct dde_pgtab_region * allocate_region()
72*433d6423SLionel Sambuc {
73*433d6423SLionel Sambuc 	struct dde_pgtab_region * res;
74*433d6423SLionel Sambuc 
75*433d6423SLionel Sambuc 	res = (struct dde_pgtab_region *)
76*433d6423SLionel Sambuc 	          ddekit_simple_malloc(sizeof(struct dde_pgtab_region));
77*433d6423SLionel Sambuc 	if (!res)
78*433d6423SLionel Sambuc 	{
79*433d6423SLionel Sambuc 		DDEBUG_MSG_ERR("Could not allocate region");
80*433d6423SLionel Sambuc 	}
81*433d6423SLionel Sambuc 	return res;
82*433d6423SLionel Sambuc }
83*433d6423SLionel Sambuc 
84*433d6423SLionel Sambuc /****************************************************************************/
85*433d6423SLionel Sambuc /*      free_region                                                         */
86*433d6423SLionel Sambuc /****************************************************************************/
free_region(struct dde_pgtab_region * r)87*433d6423SLionel Sambuc static void free_region(struct dde_pgtab_region *r)
88*433d6423SLionel Sambuc {
89*433d6423SLionel Sambuc 	ddekit_simple_free(r);
90*433d6423SLionel Sambuc }
91*433d6423SLionel Sambuc 
92*433d6423SLionel Sambuc /****************************************************************************/
93*433d6423SLionel Sambuc /*      add_region                                                          */
94*433d6423SLionel Sambuc /****************************************************************************/
add_region(struct dde_pgtab_region * r)95*433d6423SLionel Sambuc static void add_region (struct dde_pgtab_region *r)
96*433d6423SLionel Sambuc {
97*433d6423SLionel Sambuc 	r->next    = head.next;
98*433d6423SLionel Sambuc 	head.next  = r;
99*433d6423SLionel Sambuc 	r->prev    = &head;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	if (r->next) {
102*433d6423SLionel Sambuc 
103*433d6423SLionel Sambuc 		r->next->prev = r;
104*433d6423SLionel Sambuc 
105*433d6423SLionel Sambuc 	}
106*433d6423SLionel Sambuc }
107*433d6423SLionel Sambuc 
108*433d6423SLionel Sambuc /****************************************************************************/
109*433d6423SLionel Sambuc /*      rm_region                                                           */
110*433d6423SLionel Sambuc /****************************************************************************/
rm_region(struct dde_pgtab_region * r)111*433d6423SLionel Sambuc static void rm_region(struct dde_pgtab_region *r)
112*433d6423SLionel Sambuc {
113*433d6423SLionel Sambuc 	if (r->next) {
114*433d6423SLionel Sambuc 		r->next->prev = r->prev;
115*433d6423SLionel Sambuc 	}
116*433d6423SLionel Sambuc 	if (r->prev) {
117*433d6423SLionel Sambuc 		r->prev->next = r->next;
118*433d6423SLionel Sambuc 	}
119*433d6423SLionel Sambuc 	r->next = 0;
120*433d6423SLionel Sambuc 	r->prev = 0;
121*433d6423SLionel Sambuc }
122*433d6423SLionel Sambuc 
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc /****************************************************************************/
125*433d6423SLionel Sambuc /*      find_region_virt                                                    */
126*433d6423SLionel Sambuc /****************************************************************************/
find_region_virt(ddekit_addr_t va)127*433d6423SLionel Sambuc static struct dde_pgtab_region * find_region_virt(ddekit_addr_t va)
128*433d6423SLionel Sambuc {
129*433d6423SLionel Sambuc 	struct dde_pgtab_region * r;
130*433d6423SLionel Sambuc 
131*433d6423SLionel Sambuc 	for( r = head.next; r != &head ; r = r->next ) {
132*433d6423SLionel Sambuc 
133*433d6423SLionel Sambuc 		if ( (r->vm_start <= va)  && (va < (r->vm_start + r->size) ) )  {
134*433d6423SLionel Sambuc 			break;
135*433d6423SLionel Sambuc 		}
136*433d6423SLionel Sambuc 	}
137*433d6423SLionel Sambuc 
138*433d6423SLionel Sambuc 	if (r == &head) {
139*433d6423SLionel Sambuc 		DDEBUG_MSG_VERBOSE("No virt->phys mapping found for %x", va);
140*433d6423SLionel Sambuc 		r = 0;
141*433d6423SLionel Sambuc 	}
142*433d6423SLionel Sambuc 
143*433d6423SLionel Sambuc 	return r;
144*433d6423SLionel Sambuc }
145*433d6423SLionel Sambuc 
146*433d6423SLionel Sambuc /****************************************************************************/
147*433d6423SLionel Sambuc /*      find_region_phys                                                    */
148*433d6423SLionel Sambuc /****************************************************************************/
find_region_phys(ddekit_addr_t pa)149*433d6423SLionel Sambuc static struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa)
150*433d6423SLionel Sambuc {
151*433d6423SLionel Sambuc 	struct dde_pgtab_region * r;
152*433d6423SLionel Sambuc 
153*433d6423SLionel Sambuc 	for( r = head.next; r != &head ; r = r->next ) {
154*433d6423SLionel Sambuc 		if ( (r->phy_start <= pa)  && (pa < (r->phy_start + r->size) ) )
155*433d6423SLionel Sambuc 			break;
156*433d6423SLionel Sambuc 	}
157*433d6423SLionel Sambuc 
158*433d6423SLionel Sambuc 	if (r == &head)	{
159*433d6423SLionel Sambuc 		r=0;
160*433d6423SLionel Sambuc 		DDEBUG_MSG_VERBOSE("No phys->virt mapping found for %x", pa);
161*433d6423SLionel Sambuc 	}
162*433d6423SLionel Sambuc 
163*433d6423SLionel Sambuc 	return r;
164*433d6423SLionel Sambuc }
165*433d6423SLionel Sambuc 
166*433d6423SLionel Sambuc /****************************************************************************/
167*433d6423SLionel Sambuc /*      ddekit_pgtab_do_fo_each_region                                      */
168*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_do_fo_each_region(void (* func)(unsigned,unsigned))169*433d6423SLionel Sambuc void ddekit_pgtab_do_fo_each_region(void (*func) (unsigned, unsigned)) {
170*433d6423SLionel Sambuc 	struct dde_pgtab_region * r;
171*433d6423SLionel Sambuc 
172*433d6423SLionel Sambuc 	for( r = head.next; r != &head ; r = r->next ) {
173*433d6423SLionel Sambuc 		ddekit_printf("%p",r->vm_start);
174*433d6423SLionel Sambuc 		func(r->vm_start, r->size);
175*433d6423SLionel Sambuc 	}
176*433d6423SLionel Sambuc }
177*433d6423SLionel Sambuc 
178*433d6423SLionel Sambuc /*
179*433d6423SLionel Sambuc  * Interface implementation
180*433d6423SLionel Sambuc  */
181*433d6423SLionel Sambuc 
182*433d6423SLionel Sambuc /****************************************************************************/
183*433d6423SLionel Sambuc /*      ddekit_pgtab_set_region                                             */
184*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_set_region(void * virt,ddekit_addr_t phys,int pages,int type)185*433d6423SLionel Sambuc void ddekit_pgtab_set_region(void *virt, ddekit_addr_t phys, int pages, int type)
186*433d6423SLionel Sambuc {
187*433d6423SLionel Sambuc 	ddekit_pgtab_set_region_with_size(virt, phys, (4096)*pages, type);
188*433d6423SLionel Sambuc }
189*433d6423SLionel Sambuc 
190*433d6423SLionel Sambuc /****************************************************************************/
191*433d6423SLionel Sambuc /*      ddekit_pgtab_set_region_with_size                                   */
192*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_set_region_with_size(void * virt,ddekit_addr_t phys,int size,int type)193*433d6423SLionel Sambuc void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type)
194*433d6423SLionel Sambuc {
195*433d6423SLionel Sambuc 	struct dde_pgtab_region * r;
196*433d6423SLionel Sambuc 
197*433d6423SLionel Sambuc 	lock_pgtab();
198*433d6423SLionel Sambuc 
199*433d6423SLionel Sambuc 	r = allocate_region();
200*433d6423SLionel Sambuc 
201*433d6423SLionel Sambuc 	r->vm_start  = (ddekit_addr_t) virt;
202*433d6423SLionel Sambuc 	r->phy_start = phys;
203*433d6423SLionel Sambuc 	r->size      = size;
204*433d6423SLionel Sambuc 	r->type      = type;
205*433d6423SLionel Sambuc 
206*433d6423SLionel Sambuc 	add_region(r);
207*433d6423SLionel Sambuc 
208*433d6423SLionel Sambuc 	unlock_pgtab();
209*433d6423SLionel Sambuc }
210*433d6423SLionel Sambuc 
211*433d6423SLionel Sambuc 
212*433d6423SLionel Sambuc /****************************************************************************/
213*433d6423SLionel Sambuc /*      ddekit_pgtab_clear_region                                           */
214*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_clear_region(void * virt,int type)215*433d6423SLionel Sambuc void ddekit_pgtab_clear_region(void *virt, int type) {
216*433d6423SLionel Sambuc 
217*433d6423SLionel Sambuc 	struct dde_pgtab_region *r;
218*433d6423SLionel Sambuc 
219*433d6423SLionel Sambuc 	lock_pgtab();
220*433d6423SLionel Sambuc 
221*433d6423SLionel Sambuc 	r = find_region_virt((ddekit_addr_t)virt);
222*433d6423SLionel Sambuc 
223*433d6423SLionel Sambuc 	if (r)
224*433d6423SLionel Sambuc 	{
225*433d6423SLionel Sambuc 		rm_region(r);
226*433d6423SLionel Sambuc 		free_region(r);
227*433d6423SLionel Sambuc 	}
228*433d6423SLionel Sambuc 
229*433d6423SLionel Sambuc 	unlock_pgtab();
230*433d6423SLionel Sambuc 
231*433d6423SLionel Sambuc }
232*433d6423SLionel Sambuc 
233*433d6423SLionel Sambuc 
234*433d6423SLionel Sambuc /****************************************************************************/
235*433d6423SLionel Sambuc /*      ddekit_pgtab_get_physaddr                                           */
236*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_get_physaddr(const void * virt)237*433d6423SLionel Sambuc ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virt)
238*433d6423SLionel Sambuc {
239*433d6423SLionel Sambuc 	struct dde_pgtab_region *r;
240*433d6423SLionel Sambuc 	ddekit_addr_t ret = 0;
241*433d6423SLionel Sambuc 	lock_pgtab();
242*433d6423SLionel Sambuc     r = find_region_virt((ddekit_addr_t)virt);
243*433d6423SLionel Sambuc 	unlock_pgtab();
244*433d6423SLionel Sambuc 	if (r != NULL) {
245*433d6423SLionel Sambuc 
246*433d6423SLionel Sambuc 		ret =  ((ddekit_addr_t) virt - r->vm_start) + r->phy_start;
247*433d6423SLionel Sambuc 		DDEBUG_MSG_VERBOSE("pa: %p -> %p\n", virt, ret);
248*433d6423SLionel Sambuc 	}
249*433d6423SLionel Sambuc 
250*433d6423SLionel Sambuc 	return ret;
251*433d6423SLionel Sambuc }
252*433d6423SLionel Sambuc 
253*433d6423SLionel Sambuc /****************************************************************************/
254*433d6423SLionel Sambuc /*      ddekit_pgtab_get_virtaddr                                           */
255*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical)256*433d6423SLionel Sambuc ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical)
257*433d6423SLionel Sambuc {
258*433d6423SLionel Sambuc 	struct dde_pgtab_region *r;
259*433d6423SLionel Sambuc 	lock_pgtab();
260*433d6423SLionel Sambuc     r = find_region_phys((ddekit_addr_t)physical);
261*433d6423SLionel Sambuc 	unlock_pgtab();
262*433d6423SLionel Sambuc 	if (r != NULL)
263*433d6423SLionel Sambuc 	{
264*433d6423SLionel Sambuc 		return ((ddekit_addr_t) physical - r->phy_start) + r->vm_start;
265*433d6423SLionel Sambuc 	}
266*433d6423SLionel Sambuc 
267*433d6423SLionel Sambuc 	return 0;
268*433d6423SLionel Sambuc }
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc /****************************************************************************/
271*433d6423SLionel Sambuc /*      ddekit_pgtab_get_size                                               */
272*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_get_type(const void * virt)273*433d6423SLionel Sambuc int ddekit_pgtab_get_type(const void *virt)
274*433d6423SLionel Sambuc {
275*433d6423SLionel Sambuc 	/*
276*433d6423SLionel Sambuc 	 * needed for dde fbsd
277*433d6423SLionel Sambuc 	 */
278*433d6423SLionel Sambuc 	struct dde_pgtab_region *r;
279*433d6423SLionel Sambuc 
280*433d6423SLionel Sambuc 	lock_pgtab();
281*433d6423SLionel Sambuc 	r = find_region_virt((ddekit_addr_t)virt);
282*433d6423SLionel Sambuc 	unlock_pgtab();
283*433d6423SLionel Sambuc 	return r->type;
284*433d6423SLionel Sambuc }
285*433d6423SLionel Sambuc 
286*433d6423SLionel Sambuc 
287*433d6423SLionel Sambuc /****************************************************************************/
288*433d6423SLionel Sambuc /*      ddekit_pgtab_get_size                                               */
289*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_get_size(const void * virt)290*433d6423SLionel Sambuc int ddekit_pgtab_get_size(const void *virt)
291*433d6423SLionel Sambuc {
292*433d6423SLionel Sambuc 	/*
293*433d6423SLionel Sambuc 	 * needed for fbsd
294*433d6423SLionel Sambuc 	 */
295*433d6423SLionel Sambuc 	struct dde_pgtab_region *r;
296*433d6423SLionel Sambuc 
297*433d6423SLionel Sambuc 	lock_pgtab();
298*433d6423SLionel Sambuc 	r = find_region_virt((ddekit_addr_t)virt);
299*433d6423SLionel Sambuc 	unlock_pgtab();
300*433d6423SLionel Sambuc 	if(r)
301*433d6423SLionel Sambuc 		return r->size;
302*433d6423SLionel Sambuc 	else
303*433d6423SLionel Sambuc 		return 0;
304*433d6423SLionel Sambuc }
305*433d6423SLionel Sambuc 
306*433d6423SLionel Sambuc /****************************************************************************/
307*433d6423SLionel Sambuc /*      ddekit_pgtab_init                                                   */
308*433d6423SLionel Sambuc /****************************************************************************/
ddekit_pgtab_init()309*433d6423SLionel Sambuc void ddekit_pgtab_init() {
310*433d6423SLionel Sambuc 	/* called by ddekit_init() */
311*433d6423SLionel Sambuc 	ddekit_lock_init(&lock);
312*433d6423SLionel Sambuc }
313*433d6423SLionel Sambuc 
314