source: mainline/generic/src/mm/tlb.c@ 1ec1fd8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1ec1fd8 was 2bb8648, checked in by Jakub Jermar <jakub@…>, 19 years ago

Add SYS_CAP_GRANT and SYS_CAP_REVOKE syscalls.
Move SYS_PREEMPT_CONTROL to ddi.c.
Add some comments and fix some small issues.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 * Copyright (C) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/**
30 * @file tlb.c
31 * @brief Generic TLB shootdown algorithm.
32 *
33 * The algorithm implemented here is based on the CMU TLB shootdown
34 * algorithm and is further simplified (e.g. all CPUs receive all TLB
35 * shootdown messages).
36 */
37
38#include <mm/tlb.h>
39#include <mm/asid.h>
40#include <arch/mm/tlb.h>
41#include <smp/ipi.h>
42#include <synch/spinlock.h>
43#include <typedefs.h>
44#include <atomic.h>
45#include <arch/interrupt.h>
46#include <config.h>
47#include <arch.h>
48#include <panic.h>
49#include <debug.h>
50
51/**
52 * This lock is used for synchronisation between sender and
53 * recipients of TLB shootdown message. It must be acquired
54 * before CPU structure lock.
55 */
56SPINLOCK_INITIALIZE(tlblock);
57
58void tlb_init(void)
59{
60 tlb_arch_init();
61}
62
63#ifdef CONFIG_SMP
64
65/** Send TLB shootdown message.
66 *
67 * This function attempts to deliver TLB shootdown message
68 * to all other processors.
69 *
70 * This function must be called with interrupts disabled.
71 *
72 * @param type Type describing scope of shootdown.
73 * @param asid Address space, if required by type.
74 * @param page Virtual page address, if required by type.
75 * @param count Number of pages, if required by type.
76 */
77void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t count)
78{
79 int i;
80
81 CPU->tlb_active = 0;
82 spinlock_lock(&tlblock);
83
84 for (i = 0; i < config.cpu_count; i++) {
85 cpu_t *cpu;
86
87 if (i == CPU->id)
88 continue;
89
90 cpu = &cpus[i];
91 spinlock_lock(&cpu->lock);
92 if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) {
93 /*
94 * The message queue is full.
95 * Erase the queue and store one TLB_INVL_ALL message.
96 */
97 cpu->tlb_messages_count = 1;
98 cpu->tlb_messages[0].type = TLB_INVL_ALL;
99 cpu->tlb_messages[0].asid = ASID_INVALID;
100 cpu->tlb_messages[0].page = 0;
101 cpu->tlb_messages[0].count = 0;
102 } else {
103 /*
104 * Enqueue the message.
105 */
106 cpu->tlb_messages[cpu->tlb_messages_count].type = type;
107 cpu->tlb_messages[cpu->tlb_messages_count].asid = asid;
108 cpu->tlb_messages[cpu->tlb_messages_count].page = page;
109 cpu->tlb_messages[cpu->tlb_messages_count].count = count;
110 cpu->tlb_messages_count++;
111 }
112 spinlock_unlock(&cpu->lock);
113 }
114
115 tlb_shootdown_ipi_send();
116
117busy_wait:
118 for (i = 0; i < config.cpu_count; i++)
119 if (cpus[i].tlb_active)
120 goto busy_wait;
121}
122
123/** Finish TLB shootdown sequence. */
124void tlb_shootdown_finalize(void)
125{
126 spinlock_unlock(&tlblock);
127 CPU->tlb_active = 1;
128}
129
130void tlb_shootdown_ipi_send(void)
131{
132 ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
133}
134
135/** Receive TLB shootdown message. */
136void tlb_shootdown_ipi_recv(void)
137{
138 tlb_invalidate_type_t type;
139 asid_t asid;
140 __address page;
141 count_t count;
142 int i;
143
144 ASSERT(CPU);
145
146 CPU->tlb_active = 0;
147 spinlock_lock(&tlblock);
148 spinlock_unlock(&tlblock);
149
150 spinlock_lock(&CPU->lock);
151 ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN);
152
153 for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
154 type = CPU->tlb_messages[i].type;
155 asid = CPU->tlb_messages[i].asid;
156 page = CPU->tlb_messages[i].page;
157 count = CPU->tlb_messages[i].count;
158
159 switch (type) {
160 case TLB_INVL_ALL:
161 tlb_invalidate_all();
162 break;
163 case TLB_INVL_ASID:
164 tlb_invalidate_asid(asid);
165 break;
166 case TLB_INVL_PAGES:
167 ASSERT(count);
168 tlb_invalidate_pages(asid, page, count);
169 break;
170 default:
171 panic("unknown type (%d)\n", type);
172 break;
173 }
174 if (type == TLB_INVL_ALL)
175 break;
176 }
177
178 spinlock_unlock(&CPU->lock);
179 CPU->tlb_active = 1;
180}
181
182#endif /* CONFIG_SMP */
Note: See TracBrowser for help on using the repository browser.