/** * Solaris callback function for Mp event notification. * * @param CpuState The current event/state of the CPU. * @param iCpu Which CPU is this event fore. * @param pvArg Ignored. * * @remarks This function assumes index == RTCPUID. * @returns Solaris error code. */ static int rtMpNotificationCpuEvent(cpu_setup_t CpuState, int iCpu, void *pvArg) { RTMPEVENT enmMpEvent; RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; RTThreadPreemptDisable(&PreemptState); /* * Update our CPU set structures first regardless of whether we've been * scheduled on the right CPU or not, this is just atomic accounting. */ if (CpuState == CPU_ON) { enmMpEvent = RTMPEVENT_ONLINE; RTCpuSetAdd(&g_rtMpSolCpuSet, iCpu); } else if (CpuState == CPU_OFF) { enmMpEvent = RTMPEVENT_OFFLINE; RTCpuSetDel(&g_rtMpSolCpuSet, iCpu); } else return 0; /* * Since we don't absolutely need to do CPU bound code in any of the CPU offline * notification hooks, run it on the current CPU. Scheduling a callback to execute * on the CPU going offline at this point is too late and will not work reliably. */ bool fRunningOnTargetCpu = iCpu == RTMpCpuId(); if ( fRunningOnTargetCpu == true || enmMpEvent == RTMPEVENT_OFFLINE) { rtMpNotificationDoCallbacks(enmMpEvent, iCpu); } else { /* * We're not on the target CPU, schedule (synchronous) the event notification callback * to run on the target CPU i.e. the CPU that was online'd. */ RTMPARGS Args; RT_ZERO(Args); Args.pvUser1 = &enmMpEvent; Args.pvUser2 = NULL; Args.idCpu = iCpu; RTMpOnSpecific(iCpu, rtMpNotificationSolOnCurrentCpu, &Args, NULL /* pvIgnored1 */); } RTThreadPreemptRestore(&PreemptState); NOREF(pvArg); return 0; }
int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) { # ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API if (idCpu == NIL_RTCPUID) { supdrvLnxMsrProberModifyOnCpu(idCpu, pReq, NULL); return VINF_SUCCESS; } return RTMpOnSpecific(idCpu, supdrvLnxMsrProberModifyOnCpu, pReq, NULL); # else return VERR_NOT_SUPPORTED; # endif }
/** * The native callback. * * @returns NOTIFY_DONE. * @param pNotifierBlock Pointer to g_NotifierBlock. * @param ulNativeEvent The native event. * @param pvCpu The cpu id cast into a pointer value. * @remarks This can fire with preemption enabled and on any CPU. */ static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu) { int rc; bool fProcessEvent = false; RTCPUID idCpu = (uintptr_t)pvCpu; NOREF(pNotifierBlock); /* * Note that redhat/CentOS ported _some_ of the FROZEN macros * back to their 2.6.18-92.1.10.el5 kernel but actually don't * use them. Thus we have to test for both CPU_TASKS_FROZEN and * the individual event variants. */ switch (ulNativeEvent) { /* * Pick up online events or failures to go offline. * Ignore failure events for CPUs we didn't see go offline. */ # ifdef CPU_DOWN_FAILED case CPU_DOWN_FAILED: # if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN) case CPU_DOWN_FAILED_FROZEN: # endif if (!RTCpuSetIsMember(&g_MpPendingOfflineSet, idCpu)) break; /* fProcessEvents = false */ /* fall thru */ # endif case CPU_ONLINE: # if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN) case CPU_ONLINE_FROZEN: # endif # ifdef CPU_DOWN_FAILED RTCpuSetDel(&g_MpPendingOfflineSet, idCpu); # endif fProcessEvent = true; break; /* * Pick the earliest possible offline event. * The only important thing here is that we get the event and that * it's exactly one. */ # ifdef CPU_DOWN_PREPARE case CPU_DOWN_PREPARE: # if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN) case CPU_DOWN_PREPARE_FROZEN: # endif fProcessEvent = true; # else case CPU_DEAD: # if defined(CPU_TASKS_FROZEN) && defined(CPU_DEAD_FROZEN) case CPU_DEAD_FROZEN: # endif /* Don't process CPU_DEAD notifications. */ # endif # ifdef CPU_DOWN_FAILED RTCpuSetAdd(&g_MpPendingOfflineSet, idCpu); # endif break; } if (!fProcessEvent) return NOTIFY_DONE; /* * Reschedule the callbacks to fire on the specific CPU with preemption disabled. */ rc = RTMpOnSpecific(idCpu, rtMpNotificationLinuxOnCurrentCpu, pNotifierBlock, &ulNativeEvent); Assert(RT_SUCCESS(rc)); NOREF(rc); return NOTIFY_DONE; }