tlb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2004 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 
00042 #include <mm/tlb.h>
00043 #include <mm/asid.h>
00044 #include <arch/mm/tlb.h>
00045 #include <smp/ipi.h>
00046 #include <synch/spinlock.h>
00047 #include <typedefs.h>
00048 #include <atomic.h>
00049 #include <arch/interrupt.h>
00050 #include <config.h>
00051 #include <arch.h>
00052 #include <panic.h>
00053 #include <debug.h>
00054 
00060 SPINLOCK_INITIALIZE(tlblock);
00061 
00062 void tlb_init(void)
00063 {
00064         tlb_arch_init();
00065 }
00066 
00067 #ifdef CONFIG_SMP
00068 
00081 void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t count)
00082 {
00083         int i;
00084 
00085         CPU->tlb_active = 0;
00086         spinlock_lock(&tlblock);
00087         
00088         for (i = 0; i < config.cpu_count; i++) {
00089                 cpu_t *cpu;
00090                 
00091                 if (i == CPU->id)
00092                         continue;
00093 
00094                 cpu = &cpus[i];
00095                 spinlock_lock(&cpu->lock);
00096                 if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) {
00097                         /*
00098                          * The message queue is full.
00099                          * Erase the queue and store one TLB_INVL_ALL message.
00100                          */
00101                         cpu->tlb_messages_count = 1;
00102                         cpu->tlb_messages[0].type = TLB_INVL_ALL;
00103                         cpu->tlb_messages[0].asid = ASID_INVALID;
00104                         cpu->tlb_messages[0].page = 0;
00105                         cpu->tlb_messages[0].count = 0;
00106                 } else {
00107                         /*
00108                          * Enqueue the message.
00109                          */
00110                         cpu->tlb_messages[cpu->tlb_messages_count].type = type;
00111                         cpu->tlb_messages[cpu->tlb_messages_count].asid = asid;
00112                         cpu->tlb_messages[cpu->tlb_messages_count].page = page;
00113                         cpu->tlb_messages[cpu->tlb_messages_count].count = count;
00114                         cpu->tlb_messages_count++;
00115                 }
00116                 spinlock_unlock(&cpu->lock);
00117         }
00118         
00119         tlb_shootdown_ipi_send();
00120 
00121 busy_wait:      
00122         for (i = 0; i < config.cpu_count; i++)
00123                 if (cpus[i].tlb_active)
00124                         goto busy_wait;
00125 }
00126 
00128 void tlb_shootdown_finalize(void)
00129 {
00130         spinlock_unlock(&tlblock);
00131         CPU->tlb_active = 1;
00132 }
00133 
00134 void tlb_shootdown_ipi_send(void)
00135 {
00136         ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
00137 }
00138 
00140 void tlb_shootdown_ipi_recv(void)
00141 {
00142         tlb_invalidate_type_t type;
00143         asid_t asid;
00144         __address page;
00145         count_t count;
00146         int i;
00147         
00148         ASSERT(CPU);
00149         
00150         CPU->tlb_active = 0;
00151         spinlock_lock(&tlblock);
00152         spinlock_unlock(&tlblock);
00153         
00154         spinlock_lock(&CPU->lock);
00155         ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN);
00156 
00157         for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
00158                 type = CPU->tlb_messages[i].type;
00159                 asid = CPU->tlb_messages[i].asid;
00160                 page = CPU->tlb_messages[i].page;
00161                 count = CPU->tlb_messages[i].count;
00162 
00163                 switch (type) {
00164                     case TLB_INVL_ALL:
00165                         tlb_invalidate_all();
00166                         break;
00167                     case TLB_INVL_ASID:
00168                         tlb_invalidate_asid(asid);
00169                         break;
00170                     case TLB_INVL_PAGES:
00171                         ASSERT(count);
00172                         tlb_invalidate_pages(asid, page, count);
00173                         break;
00174                     default:
00175                         panic("unknown type (%d)\n", type);
00176                         break;
00177                 }
00178                 if (type == TLB_INVL_ALL)
00179                         break;
00180         }
00181         
00182         spinlock_unlock(&CPU->lock);
00183         CPU->tlb_active = 1;
00184 }
00185 
00186 #endif /* CONFIG_SMP */
00187 

Generated on Sun Jun 18 17:17:05 2006 for HelenOS Kernel (ppc32) by  doxygen 1.4.6