mpnotification-r0drv-linux.c revision 2c8aed3abc13f4e22f66eda0e135c6197eea8003
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Linux.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2008 Oracle Corporation
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * available from http://www.virtualbox.org. This file is free software;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * you can redistribute it and/or modify it under the terms of the GNU
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * General Public License (GPL) as published by the Free Software
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The contents of this file may alternatively be used under the terms
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * of the Common Development and Distribution License Version 1.0
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * VirtualBox OSE distribution, in which case the provisions of the
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * CDDL are applicable instead of those of the GPL.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * You may elect to license modified versions of this file under the
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * terms and conditions of either the GPL or the CDDL or both.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Header Files *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71) && defined(CONFIG_SMP)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Internal Functions *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Global Variables *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The notifier block we use for registering the callback.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The set of CPUs we've seen going offline recently.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * Notification wrapper that updates CPU states and invokes our notification
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * callbacks.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * @param idCpu The CPU Id.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * @param pvUser1 Pointer to the notifier_block (unused).
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * @param pvUser2 The notification event.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * @remarks This can be invoked in interrupt context.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsyncstatic void rtMpNotificationLinuxOnCurrentCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync unsigned long ulNativeEvent = *(unsigned long *)pvUser2;
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync AssertRelease(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync AssertRelease(idCpu == RTMpCpuId()); /* ASSUMES iCpu == RTCPUID */
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * The native callback.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * @returns NOTIFY_DONE.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * @param pNotifierBlock Pointer to g_NotifierBlock.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * @param ulNativeEvent The native event.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * @param pvCpu The cpu id cast into a pointer value.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync * @remarks This can fire with preemption enabled and on any CPU.
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsyncstatic int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu)
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * Note that redhat/CentOS ported _some_ of the FROZEN macros
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * back to their 2.6.18-92.1.10.el5 kernel but actually don't
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * use them. Thus we have to test for both CPU_TASKS_FROZEN and
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * the individual event variants.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * Pick up online events or failures to go offline.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * Ignore failure events for CPUs we didn't see go offline.
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync if (!RTCpuSetIsMember(&g_MpPendingOfflineSet, idCpu))
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync break; /* fProcessEvents = false */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync /* fall thru */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Pick the earliest possible offline event.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * The only important thing here is that we get the event and that
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * it's exactly one.
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DEAD_FROZEN)
181fd68b3b1a282817d722139f2a5090bb0876a9vboxsync /* Don't process CPU_DEAD notifications. */
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync * Reschedule the callbacks to fire on the specific CPU with preemption disabled.
f2054a43ed4a624a04100921b1de7ec86974ddcfvboxsync rc = RTMpOnSpecific(idCpu, rtMpNotificationLinuxOnCurrentCpu, pNotifierBlock, &ulNativeEvent);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync AssertMsgReturn(!rc, ("%d\n", rc), RTErrConvertFromErrno(rc));
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#else /* Not supported / Not needed */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif /* Not supported / Not needed */