| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: idt.c,v 1.15 2021/12/23 02:07:21 yamaguchi Exp $ */ | | 1 | /* $NetBSD: idt.c,v 1.16 2022/02/13 19:21:21 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 1997, 1998, 2000, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 1997, 1998, 2000, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace | | 8 | * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace |
9 | * Simulation Facility NASA Ames Research Center, and by Andrew Doran. | | 9 | * Simulation Facility NASA Ames Research Center, and by Andrew Doran. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -55,27 +55,27 @@ | | | @@ -55,27 +55,27 @@ |
55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
62 | * SUCH DAMAGE. | | 62 | * SUCH DAMAGE. |
63 | * | | 63 | * |
64 | * @(#)machdep.c 7.4 (Berkeley) 6/3/91 | | 64 | * @(#)machdep.c 7.4 (Berkeley) 6/3/91 |
65 | */ | | 65 | */ |
66 | | | 66 | |
67 | #include <sys/cdefs.h> | | 67 | #include <sys/cdefs.h> |
68 | __KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.15 2021/12/23 02:07:21 yamaguchi Exp $"); | | 68 | __KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.16 2022/02/13 19:21:21 riastradh Exp $"); |
69 | | | 69 | |
70 | #include "opt_pcpu_idt.h" | | 70 | #include "opt_pcpu_idt.h" |
71 | | | 71 | |
72 | #include <sys/param.h> | | 72 | #include <sys/param.h> |
73 | #include <sys/systm.h> | | 73 | #include <sys/systm.h> |
74 | #include <sys/mutex.h> | | 74 | #include <sys/mutex.h> |
75 | #include <sys/cpu.h> | | 75 | #include <sys/cpu.h> |
76 | #include <sys/atomic.h> | | 76 | #include <sys/atomic.h> |
77 | | | 77 | |
78 | #include <uvm/uvm.h> | | 78 | #include <uvm/uvm.h> |
79 | | | 79 | |
80 | #include <machine/segments.h> | | 80 | #include <machine/segments.h> |
81 | | | 81 | |
| @@ -164,77 +164,82 @@ unset_idtgate(struct gate_descriptor *id | | | @@ -164,77 +164,82 @@ unset_idtgate(struct gate_descriptor *id |
164 | */ | | 164 | */ |
165 | int | | 165 | int |
166 | idt_vec_alloc(struct idt_vec *iv, int low, int high) | | 166 | idt_vec_alloc(struct idt_vec *iv, int low, int high) |
167 | { | | 167 | { |
168 | int vec; | | 168 | int vec; |
169 | char *idt_allocmap = iv->iv_allocmap; | | 169 | char *idt_allocmap = iv->iv_allocmap; |
170 | | | 170 | |
171 | KASSERT(mutex_owned(&cpu_lock) || !mp_online); | | 171 | KASSERT(mutex_owned(&cpu_lock) || !mp_online); |
172 | | | 172 | |
173 | if (low < 0 || high >= __arraycount(iv->iv_allocmap)) | | 173 | if (low < 0 || high >= __arraycount(iv->iv_allocmap)) |
174 | return -1; | | 174 | return -1; |
175 | | | 175 | |
176 | for (vec = low; vec <= high; vec++) { | | 176 | for (vec = low; vec <= high; vec++) { |
177 | if (idt_allocmap[vec] == 0) { | | 177 | /* pairs with atomic_store_release in idt_vec_free */ |
178 | /* idt_vec_free() can be unlocked, so membar. */ | | 178 | if (atomic_load_acquire(&idt_allocmap[vec]) == 0) { |
179 | membar_sync(); | | 179 | /* |
180 | idt_allocmap[vec] = 1; | | 180 | * No ordering needed here (`relaxed') because |
| | | 181 | * access to free entries is serialized by |
| | | 182 | * cpu_lock or single-threaded operation. |
| | | 183 | */ |
| | | 184 | atomic_store_relaxed(&idt_allocmap[vec], 1); |
181 | return vec; | | 185 | return vec; |
182 | } | | 186 | } |
183 | } | | 187 | } |
184 | | | 188 | |
185 | return -1; | | 189 | return -1; |
186 | } | | 190 | } |
187 | | | 191 | |
188 | void | | 192 | void |
189 | idt_vec_reserve(struct idt_vec *iv, int vec) | | 193 | idt_vec_reserve(struct idt_vec *iv, int vec) |
190 | { | | 194 | { |
191 | int result; | | 195 | int result; |
192 | | | 196 | |
193 | KASSERT(mutex_owned(&cpu_lock) || !mp_online); | | 197 | KASSERT(mutex_owned(&cpu_lock) || !mp_online); |
194 | | | 198 | |
195 | result = idt_vec_alloc(iv, vec, vec); | | 199 | result = idt_vec_alloc(iv, vec, vec); |
196 | if (result < 0) { | | 200 | if (result < 0) { |
197 | panic("%s: failed to reserve vec %d", __func__, vec); | | 201 | panic("%s: failed to reserve vec %d", __func__, vec); |
198 | } | | 202 | } |
199 | } | | 203 | } |
200 | | | 204 | |
201 | void | | 205 | void |
202 | idt_vec_set(struct idt_vec *iv, int vec, void (*function)(void)) | | 206 | idt_vec_set(struct idt_vec *iv, int vec, void (*function)(void)) |
203 | { | | 207 | { |
204 | idt_descriptor_t *idt; | | 208 | idt_descriptor_t *idt; |
205 | char *idt_allocmap __diagused = iv->iv_allocmap; | | 209 | char *idt_allocmap __diagused = iv->iv_allocmap; |
206 | | | 210 | |
207 | KASSERT(idt_allocmap[vec] == 1); | | 211 | KASSERT(atomic_load_relaxed(&idt_allocmap[vec]) == 1); |
208 | | | 212 | |
209 | idt = iv->iv_idt; | | 213 | idt = iv->iv_idt; |
210 | set_idtgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, | | 214 | set_idtgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, |
211 | GSEL(GCODE_SEL, SEL_KPL)); | | 215 | GSEL(GCODE_SEL, SEL_KPL)); |
212 | } | | 216 | } |
213 | | | 217 | |
214 | /* | | 218 | /* |
215 | * Free IDT vector. No locking required as release is atomic. | | 219 | * Free IDT vector. No locking required as release is atomic. |
216 | */ | | 220 | */ |
217 | void | | 221 | void |
218 | idt_vec_free(struct idt_vec *iv, int vec) | | 222 | idt_vec_free(struct idt_vec *iv, int vec) |
219 | { | | 223 | { |
220 | idt_descriptor_t *idt; | | 224 | idt_descriptor_t *idt; |
221 | char *idt_allocmap = iv->iv_allocmap; | | 225 | char *idt_allocmap = iv->iv_allocmap; |
222 | | | 226 | |
223 | KASSERT(idt_allocmap[vec] == 1); | | 227 | KASSERT(atomic_load_relaxed(&idt_allocmap[vec]) == 1); |
224 | | | 228 | |
225 | idt = iv->iv_idt; | | 229 | idt = iv->iv_idt; |
226 | unset_idtgate(&idt[vec]); | | 230 | unset_idtgate(&idt[vec]); |
227 | idt_allocmap[vec] = 0; | | 231 | /* pairs with atomic_load_acquire in idt_vec_alloc */ |
| | | 232 | atomic_store_release(&idt_allocmap[vec], 0); |
228 | } | | 233 | } |
229 | | | 234 | |
230 | bool | | 235 | bool |
231 | idt_vec_is_pcpu(void) | | 236 | idt_vec_is_pcpu(void) |
232 | { | | 237 | { |
233 | | | 238 | |
234 | #ifdef PCPU_IDT | | 239 | #ifdef PCPU_IDT |
235 | return true; | | 240 | return true; |
236 | #else | | 241 | #else |
237 | return false; | | 242 | return false; |
238 | #endif | | 243 | #endif |
239 | } | | 244 | } |
240 | | | 245 | |