tlb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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          * Demap everything, especially OpenFirmware.
00086          */
00087         itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00088         dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_NUCLEUS, 0);
00089         
00090         /*
00091          * We do identity mapping of 4M-page at 4M.
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          * Register window traps can occur before MMU is enabled again.
00115          * This ensures that any such traps will be handled from 
00116          * kernel identity mapped trap handler.
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          * Identity map piece of faulting kernel address space.
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         /* TODO: write asid to some Context register and encode the register in second parameter below. */
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                 /* TODO: write asid to some Context register and encode the register in second parameter below. */
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 

Generated on Sun Jun 18 17:37:25 2006 for HelenOS Kernel (sparc64) by  doxygen 1.4.6