2
* Copyright (c) 2001-2004 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
/** @addtogroup genericmm
35
* @brief Generic TLB shootdown algorithm.
37
* The algorithm implemented here is based on the CMU TLB shootdown
38
* algorithm and is further simplified (e.g. all CPUs receive all TLB
39
* shootdown messages).
44
#include <arch/mm/tlb.h>
46
#include <synch/spinlock.h>
48
#include <arch/interrupt.h>
56
* This lock is used for synchronisation between sender and
57
* recipients of TLB shootdown message. It must be acquired
58
* before CPU structure lock.
60
SPINLOCK_INITIALIZE(tlblock);
69
/** Send TLB shootdown message.
71
* This function attempts to deliver TLB shootdown message
72
* to all other processors.
74
* This function must be called with interrupts disabled.
76
* @param type Type describing scope of shootdown.
77
* @param asid Address space, if required by type.
78
* @param page Virtual page address, if required by type.
79
* @param count Number of pages, if required by type.
81
void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
82
uintptr_t page, size_t count)
87
spinlock_lock(&tlblock);
89
for (i = 0; i < config.cpu_count; i++) {
96
spinlock_lock(&cpu->lock);
97
if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) {
99
* The message queue is full.
100
* Erase the queue and store one TLB_INVL_ALL message.
102
cpu->tlb_messages_count = 1;
103
cpu->tlb_messages[0].type = TLB_INVL_ALL;
104
cpu->tlb_messages[0].asid = ASID_INVALID;
105
cpu->tlb_messages[0].page = 0;
106
cpu->tlb_messages[0].count = 0;
109
* Enqueue the message.
111
size_t idx = cpu->tlb_messages_count++;
112
cpu->tlb_messages[idx].type = type;
113
cpu->tlb_messages[idx].asid = asid;
114
cpu->tlb_messages[idx].page = page;
115
cpu->tlb_messages[idx].count = count;
117
spinlock_unlock(&cpu->lock);
120
tlb_shootdown_ipi_send();
123
for (i = 0; i < config.cpu_count; i++)
124
if (cpus[i].tlb_active)
128
/** Finish TLB shootdown sequence. */
129
void tlb_shootdown_finalize(void)
131
spinlock_unlock(&tlblock);
135
void tlb_shootdown_ipi_send(void)
137
ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
140
/** Receive TLB shootdown message. */
141
void tlb_shootdown_ipi_recv(void)
143
tlb_invalidate_type_t type;
152
spinlock_lock(&tlblock);
153
spinlock_unlock(&tlblock);
155
spinlock_lock(&CPU->lock);
156
ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN);
158
for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
159
type = CPU->tlb_messages[i].type;
160
asid = CPU->tlb_messages[i].asid;
161
page = CPU->tlb_messages[i].page;
162
count = CPU->tlb_messages[i].count;
166
tlb_invalidate_all();
169
tlb_invalidate_asid(asid);
173
tlb_invalidate_pages(asid, page, count);
176
panic("Unknown type (%d).", type);
179
if (type == TLB_INVL_ALL)
183
spinlock_unlock(&CPU->lock);
187
#endif /* CONFIG_SMP */