Sun Feb 13 19:21:21 2022 UTC ()
x86: Membar audit in idt.c.

- idt_vec_free/alloc are obviously supposed to synchronize with a
  happens-before relation, so use release/acquire.

- There is no store-before-load ordering needed, so omit membar_sync.


(riastradh)
diff -r1.15 -r1.16 src/sys/arch/x86/x86/idt.c

cvs diff -r1.15 -r1.16 src/sys/arch/x86/x86/idt.c (expand / switch to unified diff)

--- src/sys/arch/x86/x86/idt.c 2021/12/23 02:07:21 1.15
+++ src/sys/arch/x86/x86/idt.c 2022/02/13 19:21:21 1.16
@@ -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 */
165int 165int
166idt_vec_alloc(struct idt_vec *iv, int low, int high) 166idt_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
188void 192void
189idt_vec_reserve(struct idt_vec *iv, int vec) 193idt_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
201void 205void
202idt_vec_set(struct idt_vec *iv, int vec, void (*function)(void)) 206idt_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 */
217void 221void
218idt_vec_free(struct idt_vec *iv, int vec) 222idt_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
230bool 235bool
231idt_vec_is_pcpu(void) 236idt_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