VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/freebsd/mp-r0drv-freebsd.c

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: mp-r0drv-freebsd.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, Ring-0 Driver, FreeBSD.
4 */
5
6/*
7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "the-freebsd-kernel.h"
42
43#include <iprt/mp.h>
44#include <iprt/err.h>
45#include <iprt/asm.h>
46#include <iprt/cpuset.h>
47#include "r0drv/mp-r0drv.h"
48
49
50#if __FreeBSD_version < 1200028
51# define smp_no_rendezvous_barrier smp_no_rendevous_barrier
52#endif
53
54RTDECL(RTCPUID) RTMpCpuId(void)
55{
56 return curcpu;
57}
58
59
60RTDECL(int) RTMpCurSetIndex(void)
61{
62 return curcpu;
63}
64
65
66RTDECL(int) RTMpCurSetIndexAndId(PRTCPUID pidCpu)
67{
68 return *pidCpu = curcpu;
69}
70
71
72RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
73{
74 return idCpu < RTCPUSET_MAX_CPUS && idCpu <= mp_maxid ? (int)idCpu : -1;
75}
76
77
78RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
79{
80 return (unsigned)iCpu <= mp_maxid ? (RTCPUID)iCpu : NIL_RTCPUID;
81}
82
83
84RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
85{
86 return mp_maxid;
87}
88
89
90RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
91{
92 return idCpu <= mp_maxid;
93}
94
95
96RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
97{
98 RTCPUID idCpu;
99
100 RTCpuSetEmpty(pSet);
101 idCpu = RTMpGetMaxCpuId();
102 do
103 {
104 if (RTMpIsCpuPossible(idCpu))
105 RTCpuSetAdd(pSet, idCpu);
106 } while (idCpu-- > 0);
107 return pSet;
108}
109
110
111RTDECL(RTCPUID) RTMpGetCount(void)
112{
113 return mp_maxid + 1;
114}
115
116
117RTDECL(RTCPUID) RTMpGetCoreCount(void)
118{
119 return mp_maxid + 1;
120}
121
122RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
123{
124 return idCpu <= mp_maxid
125 && !CPU_ABSENT(idCpu);
126}
127
128
129RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
130{
131 RTCPUID idCpu;
132
133 RTCpuSetEmpty(pSet);
134 idCpu = RTMpGetMaxCpuId();
135 do
136 {
137 if (RTMpIsCpuOnline(idCpu))
138 RTCpuSetAdd(pSet, idCpu);
139 } while (idCpu-- > 0);
140
141 return pSet;
142}
143
144
145RTDECL(RTCPUID) RTMpGetOnlineCount(void)
146{
147 return mp_ncpus;
148}
149
150
151/**
152 * Wrapper between the native FreeBSD per-cpu callback and PFNRTWORKER
153 * for the RTMpOnAll API.
154 *
155 * @param pvArg Pointer to the RTMPARGS package.
156 */
157static void rtmpOnAllFreeBSDWrapper(void *pvArg)
158{
159 PRTMPARGS pArgs = (PRTMPARGS)pvArg;
160 pArgs->pfnWorker(curcpu, pArgs->pvUser1, pArgs->pvUser2);
161}
162
163
164RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
165{
166 RTMPARGS Args;
167 Args.pfnWorker = pfnWorker;
168 Args.pvUser1 = pvUser1;
169 Args.pvUser2 = pvUser2;
170 Args.idCpu = NIL_RTCPUID;
171 Args.cHits = 0;
172 smp_rendezvous(NULL, rtmpOnAllFreeBSDWrapper, smp_no_rendezvous_barrier, &Args);
173 return VINF_SUCCESS;
174}
175
176
177/**
178 * Wrapper between the native FreeBSD per-cpu callback and PFNRTWORKER
179 * for the RTMpOnOthers API.
180 *
181 * @param pvArg Pointer to the RTMPARGS package.
182 */
183static void rtmpOnOthersFreeBSDWrapper(void *pvArg)
184{
185 PRTMPARGS pArgs = (PRTMPARGS)pvArg;
186 RTCPUID idCpu = curcpu;
187 if (pArgs->idCpu != idCpu)
188 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
189}
190
191
192RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
193{
194 /* Will panic if no rendezvousing cpus, so check up front. */
195 if (RTMpGetOnlineCount() > 1)
196 {
197#if __FreeBSD_version >= 900000
198 cpuset_t Mask;
199#elif __FreeBSD_version >= 700000
200 cpumask_t Mask;
201#endif
202 RTMPARGS Args;
203
204 Args.pfnWorker = pfnWorker;
205 Args.pvUser1 = pvUser1;
206 Args.pvUser2 = pvUser2;
207 Args.idCpu = RTMpCpuId();
208 Args.cHits = 0;
209#if __FreeBSD_version >= 700000
210# if __FreeBSD_version >= 900000
211 Mask = all_cpus;
212 CPU_CLR(curcpu, &Mask);
213# else
214 Mask = ~(cpumask_t)curcpu;
215# endif
216 smp_rendezvous_cpus(Mask, NULL, rtmpOnOthersFreeBSDWrapper, smp_no_rendezvous_barrier, &Args);
217#else
218 smp_rendezvous(NULL, rtmpOnOthersFreeBSDWrapper, NULL, &Args);
219#endif
220 }
221 return VINF_SUCCESS;
222}
223
224
225/**
226 * Wrapper between the native FreeBSD per-cpu callback and PFNRTWORKER
227 * for the RTMpOnSpecific API.
228 *
229 * @param pvArg Pointer to the RTMPARGS package.
230 */
231static void rtmpOnSpecificFreeBSDWrapper(void *pvArg)
232{
233 PRTMPARGS pArgs = (PRTMPARGS)pvArg;
234 RTCPUID idCpu = curcpu;
235 if (pArgs->idCpu == idCpu)
236 {
237 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
238 ASMAtomicIncU32(&pArgs->cHits);
239 }
240}
241
242
243RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
244{
245#if __FreeBSD_version >= 900000
246 cpuset_t Mask;
247#elif __FreeBSD_version >= 700000
248 cpumask_t Mask;
249#endif
250 RTMPARGS Args;
251
252 /* Will panic if no rendezvousing cpus, so make sure the cpu is online. */
253 if (!RTMpIsCpuOnline(idCpu))
254 return VERR_CPU_NOT_FOUND;
255
256 Args.pfnWorker = pfnWorker;
257 Args.pvUser1 = pvUser1;
258 Args.pvUser2 = pvUser2;
259 Args.idCpu = idCpu;
260 Args.cHits = 0;
261#if __FreeBSD_version >= 700000
262# if __FreeBSD_version >= 900000
263 CPU_SETOF(idCpu, &Mask);
264# else
265 Mask = (cpumask_t)1 << idCpu;
266# endif
267 smp_rendezvous_cpus(Mask, NULL, rtmpOnSpecificFreeBSDWrapper, smp_no_rendezvous_barrier, &Args);
268#else
269 smp_rendezvous(NULL, rtmpOnSpecificFreeBSDWrapper, NULL, &Args);
270#endif
271 return Args.cHits == 1
272 ? VINF_SUCCESS
273 : VERR_CPU_NOT_FOUND;
274}
275
276
277#if __FreeBSD_version >= 700000
278/**
279 * Dummy callback for RTMpPokeCpu.
280 * @param pvArg Ignored
281 */
282static void rtmpFreeBSDPokeCallback(void *pvArg)
283{
284 NOREF(pvArg);
285}
286
287
288RTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
289{
290#if __FreeBSD_version >= 900000
291 cpuset_t Mask;
292#elif __FreeBSD_version >= 700000
293 cpumask_t Mask;
294#endif
295
296 /* Will panic if no rendezvousing cpus, so make sure the cpu is online. */
297 if (!RTMpIsCpuOnline(idCpu))
298 return VERR_CPU_NOT_FOUND;
299
300# if __FreeBSD_version >= 900000
301 CPU_SETOF(idCpu, &Mask);
302# else
303 Mask = (cpumask_t)1 << idCpu;
304# endif
305 smp_rendezvous_cpus(Mask, NULL, rtmpFreeBSDPokeCallback, smp_no_rendezvous_barrier, NULL);
306
307 return VINF_SUCCESS;
308}
309
310#else /* < 7.0 */
311RTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
312{
313 return VERR_NOT_SUPPORTED;
314}
315#endif /* < 7.0 */
316
317
318RTDECL(bool) RTMpOnAllIsConcurrentSafe(void)
319{
320 return true;
321}
322
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use