VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/solaris/vbi/mp-r0drv-solaris.c@ 37242

Last change on this file since 37242 was 37062, checked in by vboxsync, 14 years ago

VMM: Support for online/offlining of CPUs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: mp-r0drv-solaris.c 37062 2011-05-13 10:18:29Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, Ring-0 Driver, Solaris.
4 */
5
6/*
7 * Copyright (C) 2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "../the-solaris-kernel.h"
32#include "internal/iprt.h"
33#include <iprt/mp.h>
34#include <iprt/cpuset.h>
35
36#include <iprt/asm.h>
37#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
38# include <iprt/asm-amd64-x86.h>
39#endif
40#include <iprt/err.h>
41#include "r0drv/mp-r0drv.h"
42
43
44
45RTDECL(bool) RTMpIsCpuWorkPending(void)
46{
47 return false;
48}
49
50
51RTDECL(RTCPUID) RTMpCpuId(void)
52{
53 return vbi_cpu_id();
54}
55
56
57RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
58{
59 return idCpu < RTCPUSET_MAX_CPUS && idCpu < vbi_cpu_maxcount() ? idCpu : -1;
60}
61
62
63RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
64{
65 return (unsigned)iCpu < vbi_cpu_maxcount() ? iCpu : NIL_RTCPUID;
66}
67
68
69RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
70{
71 return vbi_max_cpu_id();
72}
73
74
75RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
76{
77 /*
78 * We cannot query CPU status recursively, check cpu member from cached set.
79 */
80 if (idCpu >= vbi_cpu_count())
81 return false;
82
83 return RTCpuSetIsMember(&g_rtMpSolarisCpuSet, idCpu);
84
85#if 0
86 return idCpu < vbi_cpu_count() && vbi_cpu_online(idCpu);
87#endif
88}
89
90
91RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
92{
93 return idCpu < vbi_cpu_count();
94}
95
96
97RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
98{
99 RTCPUID idCpu;
100
101 RTCpuSetEmpty(pSet);
102 idCpu = RTMpGetMaxCpuId(); /* it's inclusive */
103 do
104 {
105 if (RTMpIsCpuPossible(idCpu))
106 RTCpuSetAdd(pSet, idCpu);
107 } while (idCpu-- > 0);
108
109 return pSet;
110}
111
112
113RTDECL(RTCPUID) RTMpGetCount(void)
114{
115 return vbi_cpu_count();
116}
117
118
119RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
120{
121 /*
122 * We cannot query CPU status recursively, return the cached set.
123 */
124 *pSet = g_rtMpSolarisCpuSet;
125 return pSet;
126
127#if 0
128 RTCPUID idCpu;
129
130 RTCpuSetEmpty(pSet);
131 idCpu = RTMpGetMaxCpuId(); /* it's inclusive */
132 do
133 {
134 if (RTMpIsCpuOnline(idCpu))
135 RTCpuSetAdd(pSet, idCpu);
136 } while (idCpu-- > 0);
137
138 return pSet;
139#endif
140}
141
142
143RTDECL(RTCPUID) RTMpGetOnlineCount(void)
144{
145 RTCPUSET Set;
146 RTMpGetOnlineSet(&Set);
147 return RTCpuSetCount(&Set);
148
149#if 0
150 int c;
151 int cnt = 0;
152
153 for (c = 0; c < vbi_cpu_count(); ++c)
154 {
155 if (vbi_cpu_online(c))
156 ++cnt;
157 }
158 return cnt;
159#endif
160}
161
162
163
164/**
165 * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
166 * for the RTMpOnAll API.
167 *
168 * @param uArgs Pointer to the RTMPARGS package.
169 * @param uIgnored1 Ignored.
170 * @param uIgnored2 Ignored.
171 */
172static int rtmpOnAllSolarisWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
173{
174 PRTMPARGS pArgs = (PRTMPARGS)(uArg);
175
176 /*
177 * Solaris CPU cross calls execute on offline CPUs too. Check our CPU cache
178 * set and ignore if it's offline.
179 */
180 if (!RTMpIsCpuOnline(RTMpCpuId()))
181 return 0;
182
183 pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
184
185 NOREF(uIgnored1);
186 NOREF(uIgnored2);
187 return 0;
188}
189
190
191RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
192{
193 RTMPARGS Args;
194 RT_ASSERT_INTS_ON();
195
196 Args.pfnWorker = pfnWorker;
197 Args.pvUser1 = pvUser1;
198 Args.pvUser2 = pvUser2;
199 Args.idCpu = NIL_RTCPUID;
200 Args.cHits = 0;
201
202 vbi_preempt_disable();
203
204 vbi_execute_on_all(rtmpOnAllSolarisWrapper, &Args);
205
206 vbi_preempt_enable();
207
208 return VINF_SUCCESS;
209}
210
211
212/**
213 * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
214 * for the RTMpOnOthers API.
215 *
216 * @param uArgs Pointer to the RTMPARGS package.
217 * @param uIgnored1 Ignored.
218 * @param uIgnored2 Ignored.
219 */
220static int rtmpOnOthersSolarisWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
221{
222 PRTMPARGS pArgs = (PRTMPARGS)(uArg);
223 RTCPUID idCpu = RTMpCpuId();
224
225 Assert(idCpu != pArgs->idCpu);
226 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
227
228 NOREF(uIgnored1);
229 NOREF(uIgnored2);
230 return 0;
231}
232
233
234RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
235{
236 RTMPARGS Args;
237 RT_ASSERT_INTS_ON();
238
239 /* The caller is supposed to have disabled preemption, but take no chances. */
240 vbi_preempt_disable();
241
242 Args.pfnWorker = pfnWorker;
243 Args.pvUser1 = pvUser1;
244 Args.pvUser2 = pvUser2;
245 Args.idCpu = RTMpCpuId();
246 Args.cHits = 0;
247
248 vbi_execute_on_others(rtmpOnOthersSolarisWrapper, &Args);
249
250 vbi_preempt_enable();
251
252 return VINF_SUCCESS;
253}
254
255
256/**
257 * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
258 * for the RTMpOnSpecific API.
259 *
260 *
261 * @param uArgs Pointer to the RTMPARGS package.
262 * @param uIgnored1 Ignored.
263 * @param uIgnored2 Ignored.
264 */
265static int rtmpOnSpecificSolarisWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
266{
267 PRTMPARGS pArgs = (PRTMPARGS)(uArg);
268 RTCPUID idCpu = RTMpCpuId();
269
270 Assert(idCpu == pArgs->idCpu);
271 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
272 ASMAtomicIncU32(&pArgs->cHits);
273
274 NOREF(uIgnored1);
275 NOREF(uIgnored2);
276 return 0;
277}
278
279
280RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
281{
282 RTMPARGS Args;
283 RT_ASSERT_INTS_ON();
284
285 if (idCpu >= vbi_cpu_count())
286 return VERR_CPU_NOT_FOUND;
287
288 if (RT_UNLIKELY(!RTMpIsCpuOnline(idCpu)))
289 return RTMpIsCpuPresent(idCpu) ? VERR_CPU_OFFLINE : VERR_CPU_NOT_FOUND;
290
291 Args.pfnWorker = pfnWorker;
292 Args.pvUser1 = pvUser1;
293 Args.pvUser2 = pvUser2;
294 Args.idCpu = idCpu;
295 Args.cHits = 0;
296
297 vbi_preempt_disable();
298
299 vbi_execute_on_one(rtmpOnSpecificSolarisWrapper, &Args, idCpu);
300
301 vbi_preempt_enable();
302
303 Assert(ASMAtomicUoReadU32(&Args.cHits) <= 1);
304
305 return ASMAtomicUoReadU32(&Args.cHits) == 1
306 ? VINF_SUCCESS
307 : VERR_CPU_NOT_FOUND;
308}
309
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette