00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <l4/dde/ddekit/pgtab.h>
00015 #include <l4/dde/ddekit/memory.h>
00016 #include <l4/dde/ddekit/panic.h>
00017
00018 #include <l4/l4rm/l4rm.h>
00019 #include <l4/lock/lock.h>
00020 #include <l4/util/macros.h>
00021
00022 #include "config.h"
00023
00024
00025
00026
00027
00028 struct pgtab_object
00029 {
00030 l4_addr_t va;
00031 l4_addr_t pa;
00032
00033
00034 l4_size_t size;
00035 unsigned type;
00036
00037 struct pgtab_object * next;
00038 struct pgtab_object * prev;
00039 };
00040
00041
00042
00043
00044 static struct pgtab_object pa_list_head =
00045 {
00046 .va = 0,
00047 .pa = 0,
00048 .size = 0,
00049 .next = &pa_list_head,
00050 .prev = &pa_list_head
00051 };
00052
00053 static l4lock_t pa_list_lock = L4LOCK_UNLOCKED;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virtual)
00066 {
00067
00068 struct pgtab_object *p = l4rm_get_userptr(virtual);
00069 if (!p) {
00070
00071 LOG_Error("no virt->phys mapping for virtual address %p", virtual);
00072 return 0;
00073 }
00074
00075
00076 l4_size_t offset = (l4_addr_t) virtual - p->va;
00077
00078 return p->pa + offset;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical)
00088 {
00089
00090 struct pgtab_object *p;
00091 ddekit_addr_t retval = 0;
00092
00093
00094 l4lock_lock(&pa_list_lock);
00095 for (p = pa_list_head.next ; p != &pa_list_head ; p = p->next) {
00096 if (p->pa <= (l4_addr_t)physical &&
00097 (l4_addr_t)physical < p->pa + p->size) {
00098 l4_size_t offset = (l4_addr_t) physical - p->pa;
00099 retval = p->va + offset;
00100 break;
00101 }
00102 }
00103 l4lock_unlock(&pa_list_lock);
00104
00105 if (!retval)
00106 LOG_Error("no phys->virt mapping for physical address %p", (void*)physical);
00107
00108 return retval;
00109 }
00110
00111
00112
00113 int ddekit_pgtab_get_type(const void *virtual)
00114 {
00115
00116 struct pgtab_object *p = l4rm_get_userptr(virtual);
00117 if (!p) {
00118
00119 LOG_Error("no virt->phys mapping for %p", virtual);
00120 return -1;
00121 }
00122
00123 return p->type;
00124 }
00125
00126
00127 int ddekit_pgtab_get_size(const void *virtual)
00128 {
00129
00130 struct pgtab_object *p = l4rm_get_userptr(virtual);
00131 if (!p) {
00132
00133 LOG_Error("no virt->phys mapping for %p", virtual);
00134 return -1;
00135 }
00136
00137 return p->size;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 void ddekit_pgtab_clear_region(void *virtual, int type)
00148 {
00149 struct pgtab_object *p;
00150
00151
00152 p = (struct pgtab_object *)l4rm_get_userptr(virtual);
00153 if (!p) {
00154
00155 LOG_Error("no virt->phys mapping for %p", virtual);
00156 return;
00157 }
00158
00159
00160
00161 l4rm_set_userptr(virtual, 0);
00162
00163
00164 l4lock_lock(&pa_list_lock);
00165 p->next->prev= p->prev;
00166 p->prev->next= p->next;
00167 l4lock_unlock(&pa_list_lock);
00168
00169
00170 ddekit_simple_free(p);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void ddekit_pgtab_set_region(void *virtual, ddekit_addr_t physical, int pages, int type)
00183 {
00184
00185 struct pgtab_object *p = ddekit_simple_malloc(sizeof(*p));
00186 if (!p) {
00187 LOG_Error("ddekit heap exhausted");
00188 return;
00189 }
00190
00191
00192 p->va = l4_trunc_page(virtual);
00193 p->pa = l4_trunc_page(physical);
00194 p->size = pages * L4_PAGESIZE;
00195 p->type = type;
00196
00197 l4lock_lock(&pa_list_lock);
00198 p->next=pa_list_head.next;
00199 p->prev=&pa_list_head;
00200 pa_list_head.next->prev=p;
00201 pa_list_head.next=p;
00202 l4lock_unlock(&pa_list_lock);
00203
00204
00205 int err = l4rm_set_userptr((void *)p->va, p);
00206 if (err) {
00207 LOG_Error("l4rm_set_userptr returned %d", err);
00208 ddekit_panic("l4rm_set_userptr");
00209 ddekit_simple_free(p);
00210 }
00211 }
00212
00213 void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type)
00214 {
00215 int p = l4_round_page(size);
00216 p >>= L4_PAGESHIFT;
00217 ddekit_pgtab_set_region(virt, phys, p, type);
00218 }
00219