00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <arch/mm/tlb.h>
00036 #include <mm/tlb.h>
00037 #include <arch/mm/frame.h>
00038 #include <arch/mm/page.h>
00039 #include <arch/mm/mmu.h>
00040 #include <mm/asid.h>
00041 #include <print.h>
00042 #include <arch/types.h>
00043 #include <typedefs.h>
00044 #include <config.h>
00045 #include <arch/trap/trap.h>
00046 #include <panic.h>
00047 #include <arch/asm.h>
00048 #include <symtab.h>
00049
00050 #include <arch/drivers/fb.h>
00051 #include <arch/drivers/i8042.h>
00052
00053 char *context_encoding[] = {
00054 "Primary",
00055 "Secondary",
00056 "Nucleus",
00057 "Reserved"
00058 };
00059
00071 void tlb_arch_init(void)
00072 {
00073 tlb_tag_access_reg_t tag;
00074 tlb_data_t data;
00075 frame_address_t fr;
00076 page_address_t pg;
00077
00078 fr.address = config.base;
00079 pg.address = config.base;
00080
00081 immu_disable();
00082 dmmu_disable();
00083
00084
00085
00086
00087 itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00088 dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00089
00090
00091
00092
00093 tag.value = ASID_KERNEL;
00094 tag.vpn = pg.vpn;
00095
00096 itlb_tag_access_write(tag.value);
00097 dtlb_tag_access_write(tag.value);
00098
00099 data.value = 0;
00100 data.v = true;
00101 data.size = PAGESIZE_4M;
00102 data.pfn = fr.pfn;
00103 data.l = true;
00104 data.cp = 1;
00105 data.cv = 1;
00106 data.p = true;
00107 data.w = true;
00108 data.g = true;
00109
00110 itlb_data_in_write(data.value);
00111 dtlb_data_in_write(data.value);
00112
00113
00114
00115
00116
00117
00118 trap_switch_trap_table();
00119
00120 tlb_invalidate_all();
00121
00122 dmmu_enable();
00123 immu_enable();
00124 }
00125
00134 void dtlb_insert_mapping(__address page, __address frame, int pagesize, bool locked, bool cacheable)
00135 {
00136 tlb_tag_access_reg_t tag;
00137 tlb_data_t data;
00138 page_address_t pg;
00139 frame_address_t fr;
00140
00141 pg.address = page;
00142 fr.address = frame;
00143
00144 tag.value = ASID_KERNEL;
00145 tag.vpn = pg.vpn;
00146
00147 dtlb_tag_access_write(tag.value);
00148
00149 data.value = 0;
00150 data.v = true;
00151 data.size = pagesize;
00152 data.pfn = fr.pfn;
00153 data.l = locked;
00154 data.cp = cacheable;
00155 data.cv = cacheable;
00156 data.p = true;
00157 data.w = true;
00158 data.g = true;
00159
00160 dtlb_data_in_write(data.value);
00161 }
00162
00164 void fast_instruction_access_mmu_miss(void)
00165 {
00166 panic("%s\n", __FUNCTION__);
00167 }
00168
00170 void fast_data_access_mmu_miss(void)
00171 {
00172 tlb_tag_access_reg_t tag;
00173 __address tpc;
00174 char *tpc_str;
00175
00176 tag.value = dtlb_tag_access_read();
00177 if (tag.context != ASID_KERNEL || tag.vpn == 0) {
00178 tpc = tpc_read();
00179 tpc_str = get_symtab_entry(tpc);
00180
00181 printf("Faulting page: %p, ASID=%d\n", tag.vpn * PAGE_SIZE, tag.context);
00182 printf("TPC=%p, (%s)\n", tpc, tpc_str ? tpc_str : "?");
00183 panic("%s\n", __FUNCTION__);
00184 }
00185
00186
00187
00188
00189 dtlb_insert_mapping(tag.vpn * PAGE_SIZE, tag.vpn * FRAME_SIZE, PAGESIZE_8K, false, true);
00190 }
00191
00193 void fast_data_access_protection(void)
00194 {
00195 panic("%s\n", __FUNCTION__);
00196 }
00197
00199 void tlb_print(void)
00200 {
00201 int i;
00202 tlb_data_t d;
00203 tlb_tag_read_reg_t t;
00204
00205 printf("I-TLB contents:\n");
00206 for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
00207 d.value = itlb_data_access_read(i);
00208 t.value = itlb_tag_read_read(i);
00209
00210 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n",
00211 i, t.vpn, t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
00212 }
00213
00214 printf("D-TLB contents:\n");
00215 for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
00216 d.value = dtlb_data_access_read(i);
00217 t.value = dtlb_tag_read_read(i);
00218
00219 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n",
00220 i, t.vpn, t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag, d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
00221 }
00222
00223 }
00224
00226 void tlb_invalidate_all(void)
00227 {
00228 int i;
00229 tlb_data_t d;
00230 tlb_tag_read_reg_t t;
00231
00232 for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
00233 d.value = itlb_data_access_read(i);
00234 if (!d.l) {
00235 t.value = itlb_tag_read_read(i);
00236 d.v = false;
00237 itlb_tag_access_write(t.value);
00238 itlb_data_access_write(i, d.value);
00239 }
00240 }
00241
00242 for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
00243 d.value = dtlb_data_access_read(i);
00244 if (!d.l) {
00245 t.value = dtlb_tag_read_read(i);
00246 d.v = false;
00247 dtlb_tag_access_write(t.value);
00248 dtlb_data_access_write(i, d.value);
00249 }
00250 }
00251
00252 }
00253
00258 void tlb_invalidate_asid(asid_t asid)
00259 {
00260
00261 itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00262 dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00263 }
00264
00271 void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt)
00272 {
00273 int i;
00274
00275 for (i = 0; i < cnt; i++) {
00276
00277 itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page + i * PAGE_SIZE);
00278 dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, page + i * PAGE_SIZE);
00279 }
00280 }
00281