mpnotification-r0drv-linux.c revision ad27e1d5e48ca41245120c331cc88b50464813ce
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/* $Id$ */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/** @file
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Linux.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2008 Oracle Corporation
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
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/*******************************************************************************
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync* Header Files *
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync*******************************************************************************/
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#include "the-linux-kernel.h"
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#include "internal/iprt.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
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync/**
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync * The set of CPUs we've seen going offline recently.
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsyncstatic RTCPUSET g_MpPendingOfflineSet;
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# 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
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync /*
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 */
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync /* ASSUMES iCpu == RTCPUID */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync switch (ulNativeEvent)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync {
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync /*
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * Pick up online events or failures to go offline.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync * Ignore failure events for CPUs we didn't see go offline.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_FAILED:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_FAILED_FROZEN:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync if (!RTCpuSetIsMember(&g_MpPendingOfflineSet, idCpu))
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return 0;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync /* fall thru */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_ONLINE:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_ONLINE_FROZEN:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetDel(&g_MpPendingOfflineSet, idCpu);
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, idCpu);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync break;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync /*
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.
931774aba1ecbdb5498169349e6ddb224e4861f0vboxsync */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_PREPARE
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_PREPARE:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DOWN_PREPARE_FROZEN:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# else
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DEAD:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# if defined(CPU_TASKS_FROZEN) && defined(CPU_DEAD_FROZEN)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync case CPU_DEAD_FROZEN:
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, idCpu);
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetAdd(&g_MpPendingOfflineSet, idCpu);
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync break;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync }
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
e12099475d7cc455a4cd3f8e36eba8c4851ee9d7vboxsync return NOTIFY_DONE;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
fc85d12482b4d79dd2dfd0989b9730433c7a45cbvboxsyncint rtR0MpNotificationNativeInit(void)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync int rc;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# ifdef CPU_DOWN_FAILED
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync RTCpuSetEmpty(&g_MpPendingOfflineSet);
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# endif
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync rc = register_cpu_notifier(&g_NotifierBlock);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync AssertMsgReturn(!rc, ("%d\n", rc), RTErrConvertFromErrno(rc));
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return VINF_SUCCESS;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
fc85d12482b4d79dd2dfd0989b9730433c7a45cbvboxsyncvoid rtR0MpNotificationNativeTerm(void)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync unregister_cpu_notifier(&g_NotifierBlock);
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#else /* Not supported / Not needed */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
fc85d12482b4d79dd2dfd0989b9730433c7a45cbvboxsyncint rtR0MpNotificationNativeInit(void)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync return VINF_SUCCESS;
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
fc85d12482b4d79dd2dfd0989b9730433c7a45cbvboxsyncvoid rtR0MpNotificationNativeTerm(void)
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync{
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync}
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync#endif /* Not supported / Not needed */
412ad5bac323727b4073056113e1d8e0faf60db3vboxsync