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