- Timestamp:
- Nov 25, 2018 1:44:41 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 126904
- Location:
- trunk/src/VBox/Additions/common/VBoxGuest
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
r75552 r75705 181 181 INSTALLS += VBoxGuest.kext 182 182 VBoxGuest.kext_INST = $(INST_ADDITIONS)/VBoxGuest.kext/Contents/ 183 VBoxGuest.kext_SOURCES = $(VBoxGuest.kext_0_OUTDIR)/Info.plist 184 VBoxGuest.kext_CLEAN = $(VBoxGuest.kext_0_OUTDIR)/Info.plist 185 186 $$(VBoxGuest.kext_0_OUTDIR)/Info.plist: \ 183 VBoxGuest.kext_SOURCES = $(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist 184 VBoxGuest.kext_CLEAN = $(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist 185 VBoxGuest.kext_BLDDIRS = $(VBoxGuest.kext_0_OUTDIR)/Contents/ 186 187 $$(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist: \ 187 188 $(PATH_SUB_CURRENT)/darwin/Info.plist \ 188 189 $(VBOX_VERSION_MK) | $$(dir $$@) … … 199 200 --output $@ \ 200 201 $< 202 203 $(evalcall2 VBOX_TEST_SIGN_KEXT,VBoxGuest) 201 204 endif # darwin 202 205 -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp
r70873 r75705 46 46 #include <iprt/initterm.h> 47 47 #include <iprt/mem.h> 48 #include <iprt/power.h> 48 49 #include <iprt/process.h> 49 #include <iprt/power.h>50 50 #include <iprt/semaphore.h> 51 51 #include <iprt/spinlock.h> … … 74 74 * Defined Constants And Macros * 75 75 *********************************************************************************************************************************/ 76 77 76 /** The system device node name. */ 78 77 #define DEVICE_NAME_SYS "vboxguest" 79 78 /** The user device node name. */ 80 79 #define DEVICE_NAME_USR "vboxguestu" 80 81 82 /** @name For debugging/whatever, now permanent. 83 * @{ */ 84 #define VBOX_PROC_SELFNAME_LEN 31 85 #define VBOX_RETRIEVE_CUR_PROC_NAME(a_Name) char a_Name[VBOX_PROC_SELFNAME_LEN + 1]; \ 86 proc_selfname(a_Name, VBOX_PROC_SELFNAME_LEN) 87 /** @} */ 81 88 82 89 … … 122 129 123 130 protected: 131 #ifdef USE_INTERRUPT_SOURCE 124 132 IOWorkLoop *m_pWorkLoop; 133 #else 134 /** Non-NULL if interrupts are registered. Probably same as getProvider(). */ 135 IOService *m_pInterruptProvider; 136 #endif 125 137 126 138 public: 139 virtual bool init(OSDictionary *pDictionary = 0); 140 virtual void free(void); 141 virtual IOService *probe(IOService *pProvider, SInt32 *pi32Score); 127 142 virtual bool start(IOService *pProvider); 128 143 virtual void stop(IOService *pProvider); 129 144 virtual bool terminate(IOOptionBits fOptions); 145 #ifdef USE_INTERRUPT_SOURCE 130 146 IOWorkLoop * getWorkLoop(); 147 #else 148 static void vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc); 149 150 #endif 131 151 }; 132 152 … … 146 166 147 167 private: 168 /** Guard against the parent class growing and us using outdated headers. */ 169 uint8_t m_abSafetyPadding[256]; 170 148 171 PVBOXGUESTSESSION m_pSession; /**< The session. */ 149 172 task_t m_Task; /**< The client task. */ … … 155 178 static void sessionClose(RTPROCESS Process); 156 179 virtual IOReturn clientClose(void); 180 virtual IOReturn clientDied(void); 181 virtual bool terminate(IOOptionBits fOptions = 0); 182 virtual bool finalize(IOOptionBits fOptions); 183 virtual void stop(IOService *pProvider); 184 185 RTR0MEMEF_NEW_AND_DELETE_OPERATORS_IOKIT(); 157 186 }; 158 187 … … 205 234 206 235 /** Major device number. */ 207 static int g_iMajorDeviceNo 236 static int g_iMajorDeviceNo = -1; 208 237 /** Registered devfs device handle. */ 209 static void *g_hDevFsDeviceSys 238 static void *g_hDevFsDeviceSys = NULL; 210 239 /** Registered devfs device handle for the user device. */ 211 static void *g_hDevFsDeviceUsr 240 static void *g_hDevFsDeviceUsr = NULL; /**< @todo 4 later */ 212 241 213 242 /** Spinlock protecting g_apSessionHashTab. */ 214 static RTSPINLOCK g_Spinlock 243 static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK; 215 244 /** Hash table */ 216 245 static PVBOXGUESTSESSION g_apSessionHashTab[19]; … … 218 247 #define SESSION_HASH(pid) ((pid) % RT_ELEMENTS(g_apSessionHashTab)) 219 248 /** The number of open sessions. */ 220 static int32_t volatile g_cSessions 221 /** The number of IOService class instances. */222 static bool volatile g_fInstantiated 249 static int32_t volatile g_cSessions = 0; 250 /** Makes sure there is only one org_virtualbox_VBoxGuest instance. */ 251 static bool volatile g_fInstantiated = 0; 223 252 /** The notifier handle for the sleep callback handler. */ 224 static IONotifier *g_pSleepNotifier = NULL; 225 253 static IONotifier *g_pSleepNotifier = NULL; 254 255 #ifdef USE_INTERRUPT_SOURCE 226 256 /* States of atimic variable aimed to protect dynamic object allocation in SMP environment. */ 227 257 #define VBOXGUEST_OBJECT_UNINITIALIZED (0) … … 231 261 /** Atomic variable used to protect work loop allocation when multiple threads attempt to obtain it. */ 232 262 static uint8_t volatile g_fWorkLoopCreated = VBOXGUEST_OBJECT_UNINITIALIZED; 263 #endif 233 264 234 265 … … 239 270 { 240 271 RT_NOREF(pKModInfo, pvData); 272 #ifdef DEBUG 273 printf("vgdrvDarwinStart\n"); 274 #endif 275 #if 0 276 gIOKitDebug |= 0x001 //kIOLogAttach 277 | 0x002 //kIOLogProbe 278 | 0x004 //kIOLogStart 279 | 0x008 //kIOLogRegister 280 | 0x010 //kIOLogMatch 281 | 0x020 //kIOLogConfig 282 ; 283 #endif 241 284 242 285 /* … … 250 293 } 251 294 295 RTLogBackdoorPrintf("VBoxGuest: RTR0Init failed with rc=%Rrc\n", rc); 252 296 printf("VBoxGuest: RTR0Init failed with rc=%d\n", rc); 253 297 return KMOD_RETURN_FAILURE; 298 } 299 300 301 /** 302 * Stop the kernel module. 303 */ 304 static kern_return_t vgdrvDarwinStop(struct kmod_info *pKModInfo, void *pvData) 305 { 306 RT_NOREF(pKModInfo, pvData); 307 308 /** @todo we need to check for VBoxSF clients? */ 309 310 RTLogBackdoorPrintf("VBoxGuest: calling RTR0TermForced ...\n"); 311 RTR0TermForced(); 312 313 RTLogBackdoorPrintf("VBoxGuest: vgdrvDarwinStop returns.\n"); 314 printf("VBoxGuest: driver unloaded\n"); 315 return KMOD_RETURN_SUCCESS; 254 316 } 255 317 … … 269 331 if (g_iMajorDeviceNo >= 0) 270 332 { 333 /** @todo limit /dev/vboxguest access. */ 271 334 g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR, 272 335 UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_SYS); … … 274 337 { 275 338 /* 276 * Register a sleep/wakeup notification callback.339 * And a all-user device. 277 340 */ 278 g_pSleepNotifier = registerPrioritySleepWakeInterest(&vgdrvDarwinSleepHandler, &g_DevExt, NULL); 279 if (g_pSleepNotifier != NULL) 341 g_hDevFsDeviceUsr = devfs_make_node(makedev(g_iMajorDeviceNo, 1), DEVFS_CHAR, 342 UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_USR); 343 if (g_hDevFsDeviceUsr != NULL) 280 344 { 281 return KMOD_RETURN_SUCCESS; 345 /* 346 * Register a sleep/wakeup notification callback. 347 */ 348 g_pSleepNotifier = registerPrioritySleepWakeInterest(&vgdrvDarwinSleepHandler, &g_DevExt, NULL); 349 if (g_pSleepNotifier != NULL) 350 return KMOD_RETURN_SUCCESS; 282 351 } 283 352 } … … 290 359 291 360 /** 292 * Stop the kernel module. 293 */ 294 static kern_return_t vgdrvDarwinStop(struct kmod_info *pKModInfo, void *pvData) 295 { 296 RT_NOREF(pKModInfo, pvData); 297 RTR0TermForced(); 298 299 printf("VBoxGuest: driver unloaded\n"); 300 return KMOD_RETURN_SUCCESS; 301 } 302 303 304 /* Unregister VBoxGuest char device */ 361 * Unregister VBoxGuest char devices and associated session spinlock. 362 */ 305 363 static int vgdrvDarwinCharDevRemove(void) 306 364 { 307 int rc = KMOD_RETURN_SUCCESS;308 309 365 if (g_pSleepNotifier) 310 366 { … … 338 394 } 339 395 340 return rc;396 return KMOD_RETURN_SUCCESS; 341 397 } 342 398 … … 361 417 362 418 /* 419 * The process issuing the request must be the current process. 420 */ 421 RTPROCESS Process = RTProcSelf(); 422 if ((int)Process != proc_pid(pProcess)) 423 return EIO; 424 425 /* 363 426 * Find the session created by org_virtualbox_VBoxGuestClient, fail 364 427 * if no such session, and mark it as opened. We set the uid & gid 365 428 * here too, since that is more straight forward at this point. 366 429 */ 367 //const bool fUnrestricted = minor(Dev) == 0;430 const bool fUnrestricted = minor(Dev) == 0; 368 431 int rc = VINF_SUCCESS; 369 432 PVBOXGUESTSESSION pSession = NULL; … … 371 434 if (pCred) 372 435 { 373 RTPROCESS Process = RTProcSelf();374 436 unsigned iHash = SESSION_HASH(Process); 375 437 RTSpinlockAcquire(g_Spinlock); … … 383 445 { 384 446 pSession->fOpened = true; 385 /*pSession->fUnrestricted = fUnrestricted; - later */447 pSession->fUserSession = !fUnrestricted; 386 448 } 387 449 else … … 431 493 * @param Dev The device number (major+minor). 432 494 * @param iCmd The IOCtl command. 433 * @param pData Pointer to the request data.495 * @param pData Pointer to the request data. 434 496 * @param fFlags Flag saying we're a character device (like we didn't know already). 435 497 * @param pProcess The process issuing this request. … … 438 500 { 439 501 RT_NOREF(Dev, fFlags); 440 //const bool fUnrestricted = minor(Dev) == 0;502 const bool fUnrestricted = minor(Dev) == 0; 441 503 const RTPROCESS Process = proc_pid(pProcess); 442 504 const unsigned iHash = SESSION_HASH(Process); … … 448 510 RTSpinlockAcquire(g_Spinlock); 449 511 pSession = g_apSessionHashTab[iHash]; 450 while (pSession && pSession->Process != Process && (/*later: pSession->fUnrestricted != fUnrestricted ||*/!pSession->fOpened))512 while (pSession && (pSession->Process != Process || pSession->fUserSession == fUnrestricted || !pSession->fOpened)) 451 513 pSession = pSession->pNextHash; 514 515 //if (RT_LIKELY(pSession)) 516 // supdrvSessionRetain(pSession); 517 452 518 RTSpinlockRelease(g_Spinlock); 453 519 if (!pSession) 454 520 { 455 Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", (int)Process, iCmd)); 521 Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", 522 (int)Process, iCmd)); 456 523 return EINVAL; 457 524 } … … 460 527 * Deal with the high-speed IOCtl. 461 528 */ 529 int rc; 462 530 if (VBGL_IOCTL_IS_FAST(iCmd)) 463 return VGDrvCommonIoCtlFast(iCmd, &g_DevExt, pSession); 464 465 return vgdrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess); 531 rc = VGDrvCommonIoCtlFast(iCmd, &g_DevExt, pSession); 532 else 533 rc = vgdrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess); 534 535 //supdrvSessionRelease(pSession); 536 return rc; 466 537 } 467 538 … … 679 750 /** 680 751 * Callback for blah blah blah. 752 * 753 * @todo move to IPRT. 681 754 */ 682 755 static IOReturn vgdrvDarwinSleepHandler(void *pvTarget, void *pvRefCon, UInt32 uMessageType, … … 727 800 * org_virtualbox_VBoxGuest 728 801 * 729 */ 730 802 * - IOService diff resync - 803 * - IOService diff resync - 804 * - IOService diff resync - 805 * 806 */ 807 808 809 /** 810 * Initialize the object. 811 */ 812 bool org_virtualbox_VBoxGuest::init(OSDictionary *pDictionary) 813 { 814 LogFlow(("IOService::init([%p], %p)\n", this, pDictionary)); 815 if (IOService::init(pDictionary)) 816 { 817 /* init members. */ 818 return true; 819 } 820 return false; 821 } 822 823 824 /** 825 * Free the object. 826 */ 827 void org_virtualbox_VBoxGuest::free(void) 828 { 829 RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might got sideways if we use LogFlow() here. weird. */ 830 IOService::free(); 831 } 832 833 834 /** 835 * Check if it's ok to start this service. 836 * It's always ok by us, so it's up to IOService to decide really. 837 */ 838 IOService *org_virtualbox_VBoxGuest::probe(IOService *pProvider, SInt32 *pi32Score) 839 { 840 LogFlow(("IOService::probe([%p])\n", this)); 841 IOService *pRet = IOService::probe(pProvider, pi32Score); 842 LogFlow(("IOService::probe([%p]) returns %p *pi32Score=%d\n", this, pRet, pi32Score ? *pi32Score : -1)); 843 return pRet; 844 } 845 846 847 /** 848 * Start this service. 849 */ 850 bool org_virtualbox_VBoxGuest::start(IOService *pProvider) 851 { 852 LogFlow(("IOService::start([%p])\n", this)); 853 854 /* 855 * Low level initialization / device initialization should be performed only once. 856 */ 857 if (ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) 858 { 859 /* 860 * Make sure it's a PCI device. 861 */ 862 m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); 863 if (m_pIOPCIDevice) 864 { 865 /* 866 * Call parent. 867 */ 868 if (IOService::start(pProvider)) 869 { 870 /* 871 * Is it the VMM device? 872 */ 873 if (isVmmDev(m_pIOPCIDevice)) 874 { 875 /* 876 * Enable I/O port and memory regions on the device. 877 */ 878 m_pIOPCIDevice->setMemoryEnable(true); 879 m_pIOPCIDevice->setIOEnable(true); 880 881 /* 882 * Region #0: I/O ports. Mandatory. 883 */ 884 IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); 885 if (pMem) 886 { 887 IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); 888 if ((IOPortBasePhys >> 16) == 0) 889 { 890 RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; 891 void *pvMMIOBase = NULL; 892 uint32_t cbMMIO = 0; 893 894 /* 895 * Region #1: Shared Memory. Technically optional. 896 */ 897 m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); 898 if (m_pMap) 899 { 900 pvMMIOBase = (void *)m_pMap->getVirtualAddress(); 901 cbMMIO = m_pMap->getLength(); 902 } 903 904 /* 905 * Initialize the device extension. 906 */ 907 int rc = VGDrvCommonInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO, 908 ARCH_BITS == 64 ? VBOXOSTYPE_MacOS_x64 : VBOXOSTYPE_MacOS, 0); 909 if (RT_SUCCESS(rc)) 910 { 911 /* 912 * Register the device nodes and enable interrupts. 913 */ 914 rc = vgdrvDarwinCharDevInit(); 915 if (rc == KMOD_RETURN_SUCCESS) 916 { 917 if (setupVmmDevInterrupts(pProvider)) 918 { 919 /* 920 * Read host configuration. 921 */ 922 VGDrvCommonProcessOptionsFromHost(&g_DevExt); 923 924 /* 925 * Just register the service and we're done! 926 */ 927 registerService(); 928 929 LogRel(("VBoxGuest: IOService started\n")); 930 return true; 931 } 932 933 LogRel(("VBoxGuest: Failed to set up interrupts\n")); 934 vgdrvDarwinCharDevRemove(); 935 } 936 else 937 LogRel(("VBoxGuest: Failed to initialize character devices (rc=%#x).\n", rc)); 938 939 VGDrvCommonDeleteDevExt(&g_DevExt); 940 } 941 else 942 LogRel(("VBoxGuest: Failed to initialize common code (rc=%Rrc).\n", rc)); 943 944 if (m_pMap) 945 { 946 m_pMap->release(); 947 m_pMap = NULL; 948 } 949 } 950 else 951 LogRel(("VBoxGuest: Bad I/O port address: %#RX64\n", (uint64_t)IOPortBasePhys)); 952 } 953 else 954 LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); 955 } 956 else 957 LogRel(("VBoxGuest: Not the VMMDev (%#x:%#x).\n", 958 m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID), m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID))); 959 960 IOService::stop(pProvider); 961 } 962 } 963 else 964 LogRel(("VBoxGuest: Provider is not an instance of IOPCIDevice.\n")); 965 966 ASMAtomicXchgBool(&g_fInstantiated, false); 967 } 968 return false; 969 } 970 971 972 /** 973 * Stop this service. 974 */ 975 void org_virtualbox_VBoxGuest::stop(IOService *pProvider) 976 { 977 #ifdef LOG_ENABLED 978 RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::stop([%p], %p)\n", this, pProvider); /* Being cautious here, no Log(). */ 979 #endif 980 AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated)); 981 982 /* Low level termination should be performed only once */ 983 if (!disableVmmDevInterrupts()) 984 printf("VBoxGuest: unable to unregister interrupt handler\n"); 985 986 vgdrvDarwinCharDevRemove(); 987 VGDrvCommonDeleteDevExt(&g_DevExt); 988 989 if (m_pMap) 990 { 991 m_pMap->release(); 992 m_pMap = NULL; 993 } 994 995 IOService::stop(pProvider); 996 997 ASMAtomicWriteBool(&g_fInstantiated, false); 998 999 printf("VBoxGuest: IOService stopped\n"); 1000 RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::stop: returning\n"); /* Being cautious here, no Log(). */ 1001 } 1002 1003 1004 /** 1005 * Termination request. 1006 * 1007 * @return true if we're ok with shutting down now, false if we're not. 1008 * @param fOptions Flags. 1009 */ 1010 bool org_virtualbox_VBoxGuest::terminate(IOOptionBits fOptions) 1011 { 1012 #ifdef LOG_ENABLED 1013 RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n", 1014 KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions); /* Being cautious here, no Log(). */ 1015 #endif 1016 1017 bool fRc; 1018 if ( KMOD_INFO_NAME.reference_count != 0 1019 || ASMAtomicUoReadS32(&g_cSessions)) 1020 fRc = false; 1021 else 1022 fRc = IOService::terminate(fOptions); 1023 1024 #ifdef LOG_ENABLED 1025 RTLogBackdoorPrintf("org_virtualbox_SupDrv::terminate: returns %d\n", fRc); /* Being cautious here, no Log(). */ 1026 #endif 1027 return fRc; 1028 } 1029 1030 #ifdef USE_INTERRUPT_SOURCE 731 1031 732 1032 /** … … 850 1150 } 851 1151 852 1152 #else /* !USE_INTERRUPT_SOURCE */ 1153 1154 /** 1155 * Implementes a IOInterruptHandler, called by provider when an interrupt occurs. 1156 */ 1157 /*static*/ void org_virtualbox_VBoxGuest::vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc) 1158 { 1159 RTLogBackdoorPrintf("vgdrvDarwinIrqHandler: %p %p %p %d\n", pTarget, pvRefCon, pNub, iSrc); 1160 RT_NOREF(pvRefCon, pNub, iSrc); 1161 1162 bool fTaken = VGDrvCommonISR(&g_DevExt); 1163 if (fTaken) 1164 { 1165 RTLogBackdoorPrintf("VBoxGuest: our interrupt!\n"); 1166 # ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP /* Turns out this isn't needed. Will ditch it later. */ 1167 /* 1168 * This is essentially what IOFilterInterruptEventSource does, only it 1169 * disables after the filter returns true and re-enables again after 1170 * the workloop job has called the handler. 1171 */ 1172 org_virtualbox_VBoxGuest *pThis = (org_virtualbox_VBoxGuest *)pTarget; 1173 if (pThis) 1174 { 1175 IOService *pProvider = pThis->m_pInterruptProvider; 1176 if (pProvider) 1177 { 1178 pProvider->disableInterrupt(0); 1179 VGDrvCommonWaitDoWakeUps(&g_DevExt); /* Could we perhaps do theses elsewhere? */ 1180 pProvider->enableInterrupt(0); 1181 return; 1182 } 1183 } 1184 VGDrvCommonWaitDoWakeUps(&g_DevExt); 1185 # endif 1186 } 1187 } 1188 1189 1190 /** 1191 * Sets up and enables interrupts on the device. 1192 * 1193 * Interrupts are handled directly, no messing around with workloops. The 1194 * rational here is is that the main job of our interrupt handler is waking up 1195 * other threads currently sitting in HGCM calls, i.e. little more effort than 1196 * waking up the workloop thread. 1197 * 1198 * @returns success indicator. Failures are fully logged. 1199 */ 1200 bool org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider) 1201 { 1202 AssertReturn(pProvider, false); 1203 1204 if (m_pInterruptProvider != pProvider) 1205 { 1206 pProvider->retain(); 1207 if (m_pInterruptProvider) 1208 m_pInterruptProvider->release(); 1209 m_pInterruptProvider = pProvider; 1210 } 1211 1212 IOReturn rc = pProvider->registerInterrupt(0 /*intIndex*/, this, vgdrvDarwinIrqHandler, this); 1213 if (rc == kIOReturnSuccess) 1214 { 1215 rc = pProvider->enableInterrupt(0 /*intIndex*/); 1216 if (rc == kIOReturnSuccess) 1217 return true; 1218 1219 LogRel(("VBoxGuest: Failed to enable interrupt: %#x\n", rc)); 1220 m_pInterruptProvider->unregisterInterrupt(0 /*intIndex*/); 1221 } 1222 else 1223 LogRel(("VBoxGuest: Failed to register interrupt: %#x\n", rc)); 1224 return false; 1225 } 1226 1227 1228 /** 1229 * Counterpart to setupVmmDevInterrupts(). 1230 */ 1231 bool org_virtualbox_VBoxGuest::disableVmmDevInterrupts(void) 1232 { 1233 if (m_pInterruptProvider) 1234 { 1235 IOReturn rc = m_pInterruptProvider->disableInterrupt(0 /*intIndex*/); 1236 AssertMsg(rc == kIOReturnSuccess, ("%#x\n", rc)); 1237 rc = m_pInterruptProvider->unregisterInterrupt(0 /*intIndex*/); 1238 AssertMsg(rc == kIOReturnSuccess, ("%#x\n", rc)); 1239 RT_NOREF_PV(rc); 1240 1241 m_pInterruptProvider->release(); 1242 m_pInterruptProvider = NULL; 1243 } 1244 1245 return true; 1246 } 1247 1248 #endif /* !USE_INTERRUPT_SOURCE */ 1249 1250 /** 1251 * Checks if it's the VMM device. 1252 * 1253 * @returns true if it is, false if it isn't. 1254 * @param pIOPCIDevice The PCI device we think might be the VMM device. 1255 */ 853 1256 bool org_virtualbox_VBoxGuest::isVmmDev(IOPCIDevice *pIOPCIDevice) 854 1257 { 855 UInt16 uVendorId, uDeviceId; 856 857 if (!pIOPCIDevice) 858 return false; 859 860 uVendorId = m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID); 861 uDeviceId = m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID); 862 863 if (uVendorId == VMMDEV_VENDORID && uDeviceId == VMMDEV_DEVICEID) 864 return true; 865 866 return true; 867 } 868 869 870 /** 871 * Start this service. 872 */ 873 bool org_virtualbox_VBoxGuest::start(IOService *pProvider) 874 { 875 /* 876 * Low level initialization / device initialization should be performed only once. 877 */ 878 if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) 879 return false; 880 881 if (!IOService::start(pProvider)) 882 return false; 883 884 m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); 885 if (m_pIOPCIDevice) 886 { 887 if (isVmmDev(m_pIOPCIDevice)) 888 { 889 /* Enable memory response from VMM device */ 890 m_pIOPCIDevice->setMemoryEnable(true); 891 m_pIOPCIDevice->setIOEnable(true); 892 893 IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); 894 if (pMem) 895 { 896 IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); 897 /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ 898 if((IOPortBasePhys >> 16) == 0) 899 { 900 901 RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; 902 void *pvMMIOBase = NULL; 903 uint32_t cbMMIO = 0; 904 m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); 905 if (m_pMap) 906 { 907 pvMMIOBase = (void *)m_pMap->getVirtualAddress(); 908 cbMMIO = m_pMap->getLength(); 909 } 910 911 int rc = VGDrvCommonInitDevExt(&g_DevExt, 912 IOPortBase, 913 pvMMIOBase, 914 cbMMIO, 915 #if ARCH_BITS == 64 916 VBOXOSTYPE_MacOS_x64, 917 #else 918 VBOXOSTYPE_MacOS, 919 #endif 920 0); 921 if (RT_SUCCESS(rc)) 922 { 923 rc = vgdrvDarwinCharDevInit(); 924 if (rc == KMOD_RETURN_SUCCESS) 925 { 926 if (setupVmmDevInterrupts(pProvider)) 927 { 928 /* 929 * Read host configuration. 930 */ 931 VGDrvCommonProcessOptionsFromHost(&g_DevExt); 932 933 /* 934 * Register the service. 935 */ 936 registerService(); 937 LogRel(("VBoxGuest: IOService started\n")); 938 return true; 939 } 940 941 LogRel(("VBoxGuest: Failed to set up interrupts\n")); 942 vgdrvDarwinCharDevRemove(); 943 } 944 else 945 LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); 946 947 VGDrvCommonDeleteDevExt(&g_DevExt); 948 } 949 else 950 LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); 951 952 if (m_pMap) 953 { 954 m_pMap->release(); 955 m_pMap = NULL; 956 } 957 } 958 } 959 else 960 LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); 961 } 962 else 963 LogRel(("VBoxGuest: Not the VMMDev (%#x:%#x).\n", 964 m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID), m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID))); 965 } 966 else 967 LogRel(("VBoxGuest: Provider is not an instance of IOPCIDevice.\n")); 968 969 ASMAtomicXchgBool(&g_fInstantiated, false); 970 IOService::stop(pProvider); 1258 if (pIOPCIDevice) 1259 { 1260 uint16_t idVendor = m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID); 1261 if (idVendor == VMMDEV_VENDORID) 1262 { 1263 uint16_t idDevice = m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID); 1264 if (idDevice == VMMDEV_DEVICEID) 1265 return true; 1266 } 1267 } 971 1268 return false; 972 1269 } 973 1270 974 975 /**976 * Stop this service.977 */978 void org_virtualbox_VBoxGuest::stop(IOService *pProvider)979 {980 /* Do not use Log*() here (in IOService instance) because its instance981 * already terminated in BSD's module unload callback! */982 Log(("org_virtualbox_VBoxGuest::stop([%p], %p)\n", this, pProvider));983 984 AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated));985 986 /* Low level termination should be performed only once */987 if (!disableVmmDevInterrupts())988 printf("VBoxGuest: unable to unregister interrupt handler\n");989 990 vgdrvDarwinCharDevRemove();991 VGDrvCommonDeleteDevExt(&g_DevExt);992 993 if (m_pMap)994 {995 m_pMap->release();996 m_pMap = NULL;997 }998 999 IOService::stop(pProvider);1000 1001 ASMAtomicWriteBool(&g_fInstantiated, false);1002 1003 printf("VBoxGuest: IOService stopped\n");1004 }1005 1006 1007 /**1008 * Termination request.1009 *1010 * @return true if we're ok with shutting down now, false if we're not.1011 * @param fOptions Flags.1012 */1013 bool org_virtualbox_VBoxGuest::terminate(IOOptionBits fOptions)1014 {1015 /* Do not use Log*() here (in IOService instance) because its instance1016 * already terminated in BSD's module unload callback! */1017 #ifdef LOG_ENABLED1018 printf("org_virtualbox_VBoxGuest::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n",1019 KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions);1020 #endif1021 1022 bool fRc;1023 if ( KMOD_INFO_NAME.reference_count != 01024 || ASMAtomicUoReadS32(&g_cSessions))1025 fRc = false;1026 else1027 fRc = IOService::terminate(fOptions);1028 1029 #ifdef LOG_ENABLED1030 printf("org_virtualbox_SupDrv::terminate: returns %d\n", fRc);1031 #endif1032 return fRc;1033 }1034 1271 1035 1272 … … 1055 1292 if (u32Type != VBOXGUEST_DARWIN_IOSERVICE_COOKIE) 1056 1293 { 1057 Log(("org_virtualbox_VBoxGuestClient::initWithTask: Bad cookie %#x\n", u32Type)); 1294 VBOX_RETRIEVE_CUR_PROC_NAME(szProcName); 1295 LogRelMax(10, ("org_virtualbox_VBoxGuestClient::initWithTask: Bad cookie %#x (%s)\n", u32Type, szProcName)); 1058 1296 return false; 1059 1297 } … … 1101 1339 { 1102 1340 m_pSession->fOpened = false; 1103 /* The fUnrestricted field isset on open. */1341 /* The Uid, Gid and fUnrestricted fields are set on open. */ 1104 1342 1105 1343 /* … … 1111 1349 1112 1350 PVBOXGUESTSESSION pCur = g_apSessionHashTab[iHash]; 1113 if (pCur && pCur->Process != m_pSession->Process) 1114 { 1115 do pCur = pCur->pNextHash; 1116 while (pCur && pCur->Process != m_pSession->Process); 1117 } 1351 while (pCur && pCur->Process != m_pSession->Process) 1352 pCur = pCur->pNextHash; 1118 1353 if (!pCur) 1119 1354 { … … 1135 1370 1136 1371 LogFlow(("org_virtualbox_VBoxGuestClient::start: already got a session for this process (%p)\n", pCur)); 1137 VGDrvCommonCloseSession(&g_DevExt, m_pSession); 1372 VGDrvCommonCloseSession(&g_DevExt, m_pSession); //supdrvSessionRelease(m_pSession); 1138 1373 } 1139 1374 … … 1211 1446 * Close the session. 1212 1447 */ 1213 VGDrvCommonCloseSession(&g_DevExt, pSession); 1448 VGDrvCommonCloseSession(&g_DevExt, pSession); // supdrvSessionRelease(m_pSession); 1214 1449 } 1215 1450 … … 1241 1476 } 1242 1477 1478 1479 /** 1480 * The client exits abnormally / forgets to do cleanups. (logging) 1481 */ 1482 IOReturn org_virtualbox_VBoxGuestClient::clientDied(void) 1483 { 1484 LogFlow(("IOService::clientDied([%p]) m_Task=%p R0Process=%p Process=%d\n", this, m_Task, RTR0ProcHandleSelf(), RTProcSelf())); 1485 1486 /* IOUserClient::clientDied() calls clientClose, so we'll just do the work there. */ 1487 return IOUserClient::clientDied(); 1488 } 1489 1490 1491 /** 1492 * Terminate the service (initiate the destruction). (logging) 1493 */ 1494 bool org_virtualbox_VBoxGuestClient::terminate(IOOptionBits fOptions) 1495 { 1496 LogFlow(("IOService::terminate([%p], %#x)\n", this, fOptions)); 1497 return IOUserClient::terminate(fOptions); 1498 } 1499 1500 1501 /** 1502 * The final stage of the client service destruction. (logging) 1503 */ 1504 bool org_virtualbox_VBoxGuestClient::finalize(IOOptionBits fOptions) 1505 { 1506 LogFlow(("IOService::finalize([%p], %#x)\n", this, fOptions)); 1507 return IOUserClient::finalize(fOptions); 1508 } 1509 1510 1511 /** 1512 * Stop the client service. (logging) 1513 */ 1514 void org_virtualbox_VBoxGuestClient::stop(IOService *pProvider) 1515 { 1516 LogFlow(("IOService::stop([%p])\n", this)); 1517 IOUserClient::stop(pProvider); 1518 } 1519 -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
r75588 r75705 4482 4482 #endif 4483 4483 4484 #if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_ DARWIN) && !defined(RT_OS_WINDOWS)4484 #if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_WINDOWS) 4485 4485 /* 4486 4486 * Do wake-ups. -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h
r75588 r75705 39 39 /** @def VBOXGUEST_USE_DEFERRED_WAKE_UP 40 40 * Defer wake-up of waiting thread when defined. */ 41 #if defined(RT_OS_ DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)41 #if defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING) 42 42 # define VBOXGUEST_USE_DEFERRED_WAKE_UP 43 43 #endif -
trunk/src/VBox/Additions/common/VBoxGuest/darwin/Info.plist
r45459 r75705 25 25 <key>IOKitDebug</key> <integer>65535</integer> 26 26 <key>IOProviderClass</key> <string>IOPCIDevice</string> 27 <key>IONameMatch</key> <string>pci80ee,cafe</string> 27 <key>IOPCIPrimaryMatch</key> <string>0xcafe80ee</string> 28 <!-- <key>IONameMatch</key> <string>pci80ee,cafe</string> --> 28 29 </dict> 29 30 </dict> -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3Lib.cpp
r69500 r75705 219 219 * before we open it via the BSD device node. 220 220 */ 221 /* IOKit */ 221 222 mach_port_t MasterPort; 222 223 kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); 223 224 if (kr != kIOReturnSuccess) 225 { 226 LogRel(("IOMasterPort -> %d\n", kr)); 224 227 return VERR_GENERAL_FAILURE; 228 } 225 229 226 230 CFDictionaryRef ClassToMatch = IOServiceMatching("org_virtualbox_VBoxGuest"); 227 231 if (!ClassToMatch) 232 { 233 LogRel(("IOServiceMatching(\"org_virtualbox_VBoxGuest\") failed.\n")); 228 234 return VERR_GENERAL_FAILURE; 235 } 229 236 230 237 io_service_t ServiceObject = IOServiceGetMatchingService(kIOMasterPortDefault, ClassToMatch); 231 238 if (!ServiceObject) 239 { 240 LogRel(("IOServiceGetMatchingService returned NULL\n")); 232 241 return VERR_NOT_FOUND; 242 } 233 243 234 244 io_connect_t uConnection; … … 236 246 IOObjectRelease(ServiceObject); 237 247 if (kr != kIOReturnSuccess) 248 { 249 LogRel(("IOServiceOpen returned %d. Driver open failed.\n", kr)); 238 250 return VERR_OPEN_FAILED; 239 251 } 252 253 /* Regular unix FD. */ 240 254 RTFILE hFile; 241 255 int rc = RTFileOpen(&hFile, pszDeviceName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 242 256 if (RT_FAILURE(rc)) 243 257 { 258 LogRel(("RTFileOpen(%s) returned %Rrc. Driver open failed.\n", pszDeviceName, rc)); 244 259 IOServiceClose(uConnection); 245 260 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.