mpnotification-r0drv-linux.c revision 412ad5bac323727b4073056113e1d8e0faf60db3
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/* $Id$ */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/** @file
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Linux.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync *
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 *
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 *
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * additional information or have any questions.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Header Files *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include "the-linux-kernel.h"
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include <iprt/mp.h>
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include <iprt/err.h>
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include <iprt/cpuset.h>
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include "r0drv/mp-r0drv.h"
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 71) && defined(CONFIG_SMP)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Internal Functions *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Global Variables *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/**
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The notifier block we use for registering the callback.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic struct notifier_block g_NotifierBlock =
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync .notifier_call = rtMpNotificationLinuxCallback,
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync .next = NULL,
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync .priority = 0
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync};
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/**
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The set of CPUs we've seen going offline recently.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic RTCPUSET g_MpPendingOfflineSet;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/**
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The native callback.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * @returns 0.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * @param pNotifierBlock Pointer to g_NotifierBlock.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * @param ulNativeEvent The native event.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * @param pvCpu The cpu id cast into a pointer value.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCPUID idCpu = (uintptr_t)pvCpu;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync NOREF(pNotifierBlock);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync /* ASSUMES iCpu == RTCPUID */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync switch (ulNativeEvent)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync {
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_FAILED:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# ifdef CPU_TASKS_FROZEN
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_FAILED_FROZEN:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync if (!RTCpuSetIsMember(&g_MpPendingOfflineSet, idCpu))
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return 0;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync /* fall thru */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_ONLINE:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# ifdef CPU_TASKS_FROZEN
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_ONLINE_FROZEN:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetDel(&g_MpPendingOfflineSet, idCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync break;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#ifdef CPU_DOWN_PREPARE
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_PREPARE:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# ifdef CPU_TASKS_FROZEN
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_PREPARE_FROZEN:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#else
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DEAD:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# ifdef CPU_TASKS_FROZEN
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DEAD_FROZEN:
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetAdd(&g_MpPendingOfflineSet, idCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync break;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync }
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return 0;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncint rtR0MpNotificationNativeInit(void *pvOS)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync int rc;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync NOREF(pvOS);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetEmpty(&g_MpPendingOfflineSet);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rc = register_cpu_notifier(&g_NotifierBlock);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync AssertMsgReturn(!rc, ("%d\n", rc), RTErrConvertFromErrno(rc));
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return VINF_SUCCESS;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncvoid rtR0MpNotificationNativeTerm(void *pvOS)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync unregister_cpu_notifier(&g_NotifierBlock);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#else /* Not supported / Not needed */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncint rtR0MpNotificationNativeInit(void *pvOS)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync NOREF(pvOS);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return VINF_SUCCESS;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncvoid rtR0MpNotificationNativeTerm(void *pvOS)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync NOREF(pvOS);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif /* Not supported / Not needed */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync