Changeset d1e414c in mainline for generic/src/mm/tlb.c
- Timestamp:
- 2006-03-15T00:51:25Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 91d5ad6
- Parents:
- 51cc6bf6
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/tlb.c
r51cc6bf6 rd1e414c 28 28 29 29 #include <mm/tlb.h> 30 #include <mm/asid.h> 30 31 #include <arch/mm/tlb.h> 31 32 #include <smp/ipi.h> … … 37 38 #include <arch.h> 38 39 #include <panic.h> 40 #include <debug.h> 39 41 42 /** 43 * This lock is used for synchronisation between sender and 44 * recipients of TLB shootdown message. It must be acquired 45 * before CPU structure lock. 46 */ 40 47 SPINLOCK_INITIALIZE(tlblock); 41 48 … … 46 53 47 54 #ifdef CONFIG_SMP 48 /* must be called with interrupts disabled */ 49 void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt) 55 56 /** Send TLB shootdown message. 57 * 58 * This function attempts to deliver TLB shootdown message 59 * to all other processors. 60 * 61 * This function must be called with interrupts disabled. 62 * 63 * @param type Type describing scope of shootdown. 64 * @param asid Address space, if required by type. 65 * @param page Virtual page address, if required by type. 66 * @param count Number of pages, if required by type. 67 */ 68 void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t count) 50 69 { 51 70 int i; … … 54 73 spinlock_lock(&tlblock); 55 74 56 /* 57 * TODO: wrap parameters into a message and 58 * dispatch it to all CPUs excluding this one. 59 */ 75 for (i = 0; i < config.cpu_count; i++) { 76 cpu_t *cpu; 77 78 if (i == CPU->id) 79 continue; 80 81 cpu = &cpus[i]; 82 spinlock_lock(&cpu->lock); 83 if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) { 84 /* 85 * The message queue is full. 86 * Erase the queue and store one TLB_INVL_ALL message. 87 */ 88 cpu->tlb_messages_count = 1; 89 cpu->tlb_messages[0].type = TLB_INVL_ALL; 90 cpu->tlb_messages[0].asid = ASID_INVALID; 91 cpu->tlb_messages[0].page = 0; 92 cpu->tlb_messages[0].count = 0; 93 } else { 94 /* 95 * Enqueue the message. 96 */ 97 cpu->tlb_messages[cpu->tlb_messages_count].type = type; 98 cpu->tlb_messages[cpu->tlb_messages_count].asid = asid; 99 cpu->tlb_messages[cpu->tlb_messages_count].page = page; 100 cpu->tlb_messages[cpu->tlb_messages_count].count = count; 101 cpu->tlb_messages_count++; 102 } 103 spinlock_unlock(&cpu->lock); 104 } 60 105 61 106 tlb_shootdown_ipi_send(); 62 107 63 108 busy_wait: 64 for (i = 0; i <config.cpu_count; i++)109 for (i = 0; i < config.cpu_count; i++) 65 110 if (cpus[i].tlb_active) 66 111 goto busy_wait; 67 112 } 68 113 114 /** Finish TLB shootdown sequence. */ 69 115 void tlb_shootdown_finalize(void) 70 116 { … … 78 124 } 79 125 126 /** Receive TLB shootdown message. */ 80 127 void tlb_shootdown_ipi_recv(void) 81 128 { 129 tlb_invalidate_type_t type; 130 asid_t asid; 131 __address page; 132 count_t count; 133 int i; 134 82 135 CPU->tlb_active = 0; 83 136 spinlock_lock(&tlblock); 84 137 spinlock_unlock(&tlblock); 85 tlb_invalidate_all(); /* TODO: be more finer-grained in what to invalidate */ 138 139 spinlock_lock(&CPU->lock); 140 ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN); 141 142 for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) { 143 type = CPU->tlb_messages[i].type; 144 asid = CPU->tlb_messages[i].asid; 145 page = CPU->tlb_messages[i].page; 146 count = CPU->tlb_messages[i].count; 147 148 switch (type) { 149 case TLB_INVL_ALL: 150 tlb_invalidate_all(); 151 break; 152 case TLB_INVL_ASID: 153 tlb_invalidate_asid(asid); 154 break; 155 case TLB_INVL_PAGES: 156 ASSERT(count); 157 tlb_invalidate_pages(asid, page, count); 158 break; 159 default: 160 panic("unknown type (%d)\n", type); 161 break; 162 } 163 if (type == TLB_INVL_ALL) 164 break; 165 } 166 167 spinlock_unlock(&CPU->lock); 86 168 CPU->tlb_active = 1; 87 169 } 170 88 171 #endif /* CONFIG_SMP */
Note:
See TracChangeset
for help on using the changeset viewer.