mp-r0drv-linux.c revision c2ac210bd84591123bb8803712887e2b016cb78f
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/* $Id$ */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync/** @file
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * IPRT - Multiprocessor, Ring-0 Driver, Linux.
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2008 Oracle Corporation
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync *
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * available from http://www.virtualbox.org. This file is free software;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * VirtualBox OSE distribution, in which case the provisions of the
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * CDDL are applicable instead of those of the GPL.
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync *
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * You may elect to license modified versions of this file under the
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * terms and conditions of either the GPL or the CDDL or both.
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync/*******************************************************************************
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync* Header Files *
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync*******************************************************************************/
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#include "the-linux-kernel.h"
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#include "internal/iprt.h"
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#include <iprt/mp.h>
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#include <iprt/cpuset.h>
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#include <iprt/err.h>
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#include <iprt/asm.h>
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#include "r0drv/mp-r0drv.h"
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRTDECL(RTCPUID) RTMpCpuId(void)
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync{
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return smp_processor_id();
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync}
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsyncRT_EXPORT_SYMBOL(RTMpCpuId);
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncRTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return idCpu < RTCPUSET_MAX_CPUS && idCpu < NR_CPUS ? (int)idCpu : -1;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRT_EXPORT_SYMBOL(RTMpCpuIdToSetIndex);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsyncRTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return iCpu < NR_CPUS ? (RTCPUID)iCpu : NIL_RTCPUID;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRT_EXPORT_SYMBOL(RTMpCpuIdFromSetIndex);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRTDECL(RTCPUID) RTMpGetMaxCpuId(void)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return NR_CPUS - 1; //???
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsyncRT_EXPORT_SYMBOL(RTMpGetMaxCpuId);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#if defined(CONFIG_SMP)
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync if (RT_UNLIKELY(idCpu >= NR_CPUS))
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return false;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync# if defined(cpu_possible)
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return cpu_possible(idCpu);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync# else /* < 2.5.29 */
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return idCpu < (RTCPUID)smp_num_cpus;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync# endif
fe96bc0e43d9c137304462ef8c2d79cbff22446fvboxsync#else
fa033b734cf3b131680f290326ccbbd23c42946bvboxsync return idCpu == RTMpCpuId();
fe96bc0e43d9c137304462ef8c2d79cbff22446fvboxsync#endif
fe96bc0e43d9c137304462ef8c2d79cbff22446fvboxsync}
fe96bc0e43d9c137304462ef8c2d79cbff22446fvboxsyncRT_EXPORT_SYMBOL(RTMpIsCpuPossible);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
fa033b734cf3b131680f290326ccbbd23c42946bvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync RTCPUID idCpu;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync RTCpuSetEmpty(pSet);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync idCpu = RTMpGetMaxCpuId();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync do
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync if (RTMpIsCpuPossible(idCpu))
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync RTCpuSetAdd(pSet, idCpu);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync } while (idCpu-- > 0);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return pSet;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncRT_EXPORT_SYMBOL(RTMpGetSet);
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncRTDECL(RTCPUID) RTMpGetCount(void)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#ifdef CONFIG_SMP
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# if defined(CONFIG_HOTPLUG_CPU) /* introduced & uses cpu_present */
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync return num_present_cpus();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# elif defined(num_possible_cpus)
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync return num_possible_cpus();
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return smp_num_cpus;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync# else
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCPUSET Set;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync RTMpGetSet(&Set);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return RTCpuSetCount(&Set);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# endif
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#else
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return 1;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#endif
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncRT_EXPORT_SYMBOL(RTMpGetCount);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncRTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#ifdef CONFIG_SMP
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (RT_UNLIKELY(idCpu >= NR_CPUS))
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return false;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync# ifdef cpu_online
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return cpu_online(idCpu);
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync# else /* 2.4: */
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync return cpu_online_map & RT_BIT_64(idCpu);
aa32d4906f2f685992091893d5abdf27a2352a85vboxsync# endif
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#else
aa32d4906f2f685992091893d5abdf27a2352a85vboxsync return idCpu == RTMpCpuId();
e3f5c51715cbf77ae2d2e9d05bafd00d69b1bec9vboxsync#endif
aa32d4906f2f685992091893d5abdf27a2352a85vboxsync}
aa32d4906f2f685992091893d5abdf27a2352a85vboxsyncRT_EXPORT_SYMBOL(RTMpIsCpuOnline);
aa32d4906f2f685992091893d5abdf27a2352a85vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#ifdef CONFIG_SMP
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCPUID idCpu;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCpuSetEmpty(pSet);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync idCpu = RTMpGetMaxCpuId();
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync do
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync {
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync if (RTMpIsCpuOnline(idCpu))
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCpuSetAdd(pSet, idCpu);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync } while (idCpu-- > 0);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#else
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCpuSetEmpty(pSet);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCpuSetAdd(pSet, RTMpCpuId());
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#endif
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync return pSet;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync}
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRT_EXPORT_SYMBOL(RTMpGetOnlineSet);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRTDECL(RTCPUID) RTMpGetOnlineCount(void)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#ifdef CONFIG_SMP
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# if defined(num_online_cpus)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return num_online_cpus();
b514c03a427443a7ad18c1202d2ee7acc47cf9afvboxsync# else
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTCPUSET Set;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync RTMpGetOnlineSet(&Set);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return RTCpuSetCount(&Set);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync# endif
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync#else
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return 1;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#endif
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRT_EXPORT_SYMBOL(RTMpGetOnlineCount);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRTDECL(bool) RTMpIsCpuWorkPending(void)
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync{
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync /** @todo (not used on non-Windows platforms yet). */
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync return false;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync}
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsyncRT_EXPORT_SYMBOL(RTMpIsCpuWorkPending);
fe813b3594039ba864493438e78ee0e7132bc445vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync/**
b514c03a427443a7ad18c1202d2ee7acc47cf9afvboxsync * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync *
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync * @param pvInfo Pointer to the RTMPARGS package.
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncstatic void rtmpLinuxWrapper(void *pvInfo)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync ASMAtomicIncU32(&pArgs->cHits);
914d33aebb63d8c288dfd1b7e74f8e2acf3eaa66vboxsync pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync int rc;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync RTMPARGS Args;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pfnWorker = pfnWorker;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pvUser1 = pvUser1;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pvUser2 = pvUser2;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.idCpu = NIL_RTCPUID;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.cHits = 0;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rc = on_each_cpu(rtmpLinuxWrapper, &Args, 1 /* wait */);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rc = on_each_cpu(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#else /* older kernels */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# ifdef preempt_disable
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync preempt_disable();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# endif
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync local_irq_disable();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rtmpLinuxWrapper(&Args);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync local_irq_enable();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync# ifdef preempt_enable
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync preempt_enable();
c6958b923ed12aadcf58ebbdbc80aadebbd9493evboxsync# endif
fe813b3594039ba864493438e78ee0e7132bc445vboxsync#endif /* older kernels */
c6958b923ed12aadcf58ebbdbc80aadebbd9493evboxsync Assert(rc == 0); NOREF(rc);
c6958b923ed12aadcf58ebbdbc80aadebbd9493evboxsync return VINF_SUCCESS;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRT_EXPORT_SYMBOL(RTMpOnAll);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync int rc;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync RTMPARGS Args;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pfnWorker = pfnWorker;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pvUser1 = pvUser1;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Args.pvUser2 = pvUser2;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync Args.idCpu = NIL_RTCPUID;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync Args.cHits = 0;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#ifdef preempt_disable
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync preempt_disable();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#endif
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rc = smp_call_function(rtmpLinuxWrapper, &Args, 1 /* wait */);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#else /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#endif /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#ifdef preempt_enable
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync preempt_enable();
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#endif
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
b1cc88518a7578ee20491f3d97b9792c24c6428dvboxsync Assert(rc == 0); NOREF(rc);
fe813b3594039ba864493438e78ee0e7132bc445vboxsync return VINF_SUCCESS;
b1cc88518a7578ee20491f3d97b9792c24c6428dvboxsync}
b1cc88518a7578ee20491f3d97b9792c24c6428dvboxsyncRT_EXPORT_SYMBOL(RTMpOnOthers);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync/**
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * employed by RTMpOnSpecific on older kernels that lacks smp_call_function_single.
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync *
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * @param pvInfo Pointer to the RTMPARGS package.
362838d79d234a41380be42aae9118850cc3c929vboxsync */
362838d79d234a41380be42aae9118850cc3c929vboxsyncstatic void rtmpOnSpecificLinuxWrapper(void *pvInfo)
362838d79d234a41380be42aae9118850cc3c929vboxsync{
362838d79d234a41380be42aae9118850cc3c929vboxsync PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
362838d79d234a41380be42aae9118850cc3c929vboxsync RTCPUID idCpu = RTMpCpuId();
bc36547e8dd3d35e5f756643a267bbe01e2c1d4cvboxsync
bc36547e8dd3d35e5f756643a267bbe01e2c1d4cvboxsync if (idCpu == pArgs->idCpu)
362838d79d234a41380be42aae9118850cc3c929vboxsync {
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
362838d79d234a41380be42aae9118850cc3c929vboxsync ASMAtomicIncU32(&pArgs->cHits);
362838d79d234a41380be42aae9118850cc3c929vboxsync }
362838d79d234a41380be42aae9118850cc3c929vboxsync}
362838d79d234a41380be42aae9118850cc3c929vboxsync#endif
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsyncRTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync{
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync int rc;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync RTMPARGS Args;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync Args.pfnWorker = pfnWorker;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync Args.pvUser1 = pvUser1;
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync Args.pvUser2 = pvUser2;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync Args.idCpu = idCpu;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync Args.cHits = 0;
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync if (!RTMpIsCpuPossible(idCpu))
22bdb1ce26b2d5a41d1b071c16f1078e5348bb0dvboxsync return VERR_CPU_NOT_FOUND;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# ifdef preempt_disable
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync preempt_disable();
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync# endif
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (idCpu != RTMpCpuId())
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (RTMpIsCpuOnline(idCpu))
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 1 /* wait */);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync#else /* older kernels */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = smp_call_function(rtmpOnSpecificLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync#endif /* older kernels */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(rc == 0);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = Args.cHits ? VINF_SUCCESS : VERR_CPU_OFFLINE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync else
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = VERR_CPU_OFFLINE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync else
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rtmpLinuxWrapper(&Args);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = VINF_SUCCESS;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync# ifdef preempt_enable
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync preempt_enable();
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync# endif
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync NOREF(rc);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return rc;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync}
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncRT_EXPORT_SYMBOL(RTMpOnSpecific);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/**
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Dummy callback used by RTMpPokeCpu.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync *
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync * @param pvInfo Ignored.
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsyncstatic void rtmpLinuxPokeCpuCallback(void *pvInfo)
cba6719bd64ec749967bbe931230452664109857vboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync NOREF(pvInfo);
cba6719bd64ec749967bbe931230452664109857vboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#endif
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncRTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync{
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync int rc;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (!RTMpIsCpuPossible(idCpu))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return VERR_CPU_NOT_FOUND;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync if (!RTMpIsCpuOnline(idCpu))
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return VERR_CPU_OFFLINE;
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync rc = smp_call_function_single(idCpu, rtmpLinuxPokeCpuCallback, NULL, 0 /* wait */);
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync rc = smp_call_function_single(idCpu, rtmpLinuxPokeCpuCallback, NULL, 0 /* retry */, 0 /* wait */);
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# else /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# error oops
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync# endif /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync Assert(rc == 0);
0f1e77149ab5ab40fa2bd74a5330e087416b3c7bvboxsync return VINF_SUCCESS;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#else /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync /* no unicast here? */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync return VERR_NOT_SUPPORTED;
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync#endif /* older kernels */
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsync}
5b1d6bab9f4cf5dacf1883e7c4a40c84349f597fvboxsyncRT_EXPORT_SYMBOL(RTMpPokeCpu);
cba6719bd64ec749967bbe931230452664109857vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync