Changeset 9470 in vbox for trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
- Timestamp:
- Jun 6, 2008 12:19:12 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
r9444 r9470 253 253 static int supdrvGipCreate(PSUPDRVDEVEXT pDevExt); 254 254 static void supdrvGipDestroy(PSUPDRVDEVEXT pDevExt); 255 static DECLCALLBACK(void) supdrvGipTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 255 static DECLCALLBACK(void) supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 256 static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 257 static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser); 256 258 #endif 257 259 … … 3748 3750 3749 3751 /* 3750 * Find a reasonable update interval, something close to 10ms would be nice, 3751 * and create a recurring timer. 3752 * Find a reasonable update interval and initialize the structure. 3752 3753 */ 3753 3754 u32Interval = u32SystemResolution = RTTimerGetSystemGranularity(); … … 3755 3756 u32Interval += u32SystemResolution; 3756 3757 3757 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0, supdrvGipTimer, pDevExt); 3758 if (RT_FAILURE(rc)) 3759 { 3760 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %RU32 ns interval. rc=%d\n", u32Interval, rc)); 3758 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/); 3759 3760 /* 3761 * Create the timer. 3762 * If CPU_ALL isn't supported we'll have to fall back to synchronous mode. 3763 */ 3764 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 3765 { 3766 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL, supdrvGipAsyncTimer, pDevExt); 3767 if (rc == VERR_NOT_SUPPORTED) 3768 { 3769 OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n")); 3770 pGip->u32Mode = SUPGIPMODE_SYNC_TSC; 3771 } 3772 } 3773 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 3774 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0, supdrvGipSyncTimer, pDevExt); 3775 if (RT_SUCCESS(rc)) 3776 { 3777 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 3778 rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt); 3779 if (RT_SUCCESS(rc)) 3780 { 3781 /* 3782 * We're good. 3783 */ 3784 dprintf(("supdrvGipCreate: %ld ns interval.\n", (long)u32Interval)); 3785 return VINF_SUCCESS; 3786 } 3787 3788 OSDBGPRINT(("supdrvGipCreate: failed register MP event notfication. rc=%d\n", rc)); 3789 } 3790 else 3791 { 3792 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %ld ns interval. rc=%d\n", (long)u32Interval, rc)); 3761 3793 Assert(!pDevExt->pGipTimer); 3762 supdrvGipDestroy(pDevExt); 3763 return rc; 3764 } 3765 3766 /* 3767 * We're good. 3768 */ 3769 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/); 3770 return VINF_SUCCESS; 3794 } 3795 supdrvGipDestroy(pDevExt); 3796 return rc; 3771 3797 } 3772 3798 … … 3822 3848 3823 3849 /** 3824 * Timer callback function .3850 * Timer callback function sync GIP mode. 3825 3851 * @param pTimer The timer. 3826 3852 * @param pvUser The device extension. 3827 * @param iTick The current tick. 3828 */ 3829 static DECLCALLBACK(void) supdrvGipTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 3853 */ 3854 static DECLCALLBACK(void) supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 3830 3855 { 3831 3856 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 3832 3857 supdrvGipUpdate(pDevExt->pGip, RTTimeSystemNanoTS()); 3833 NOREF(iTick); 3834 } 3858 } 3859 3860 3861 /** 3862 * Timer callback function for async GIP mode. 3863 * @param pTimer The timer. 3864 * @param pvUser The device extension. 3865 */ 3866 static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick) 3867 { 3868 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 3869 RTCPUID idCpu = RTMpCpuId(); 3870 uint64_t NanoTS = RTTimeSystemNanoTS(); 3871 3872 if (pDevExt->idGipMaster == idCpu) 3873 supdrvGipUpdate(pDevExt->pGip, NanoTS); 3874 else 3875 supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, ASMGetApicId()); 3876 } 3877 3878 3879 /** 3880 * Multiprocessor event notification callback. 3881 * 3882 * This is used to make sue that the GIP master gets passed on to 3883 * another CPU. 3884 * 3885 * @param enmEvent The event. 3886 * @param idCpu The cpu it applies to. 3887 * @param pvUser Pointer to the device extension. 3888 */ 3889 static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser) 3890 { 3891 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 3892 if (enmEvent == RTMPEVENT_OFFLINE) 3893 { 3894 RTCPUID idGipMaster; 3895 ASMAtomicReadSize(&pDevExt->idGipMaster, &idGipMaster); 3896 if (idGipMaster == idCpu) 3897 { 3898 /* 3899 * Find a new GIP master. 3900 */ 3901 bool fIgnored; 3902 unsigned i; 3903 RTCPUID idNewGipMaster = NIL_RTCPUID; 3904 RTCPUSET OnlineCpus; 3905 RTMpGetOnlineSet(&OnlineCpus); 3906 3907 for (i = 0; i < RTCPUSET_MAX_CPUS; i++) 3908 { 3909 RTCPUID idCurCpu = RTMpCpuIdFromSetIndex(i); 3910 if ( RTCpuSetIsMember(&OnlineCpus, idCurCpu) 3911 && idCurCpu != idGipMaster) 3912 { 3913 idNewGipMaster = idCurCpu; 3914 break; 3915 } 3916 } 3917 3918 dprintf(("supdrvGipMpEvent: Gip master %#lx -> %#lx\n", (long)idGipMaster, (long)idNewGipMaster)); 3919 ASMAtomicCmpXchgSize(&pDevExt->idGipMaster, idNewGipMaster, idGipMaster, fIgnored); 3920 NOREF(fIgnored); 3921 } 3922 } 3923 } 3924 3835 3925 #endif /* USE_NEW_OS_INTERFACE_FOR_GIP */ 3836 3926 … … 3907 3997 static SUPGIPMODE supdrvGipDeterminTscMode(PSUPDRVDEVEXT pDevExt) 3908 3998 { 3909 #ifndef USE_NEW_OS_INTERFACE_FOR_GIP3910 3999 /* 3911 4000 * The problem here is that AMD processors with power management features … … 3919 4008 * can be relied upon to have somewhat uniform TSC between the cpus. 3920 4009 */ 4010 # ifdef RT_OS_WINDOWS /** @todo fix RTMpGetCount() wrt to IRQL. */ 3921 4011 if (supdrvOSGetCPUCount(pDevExt) > 1) 4012 # else 4013 if (RTMpGetCount() > 1) 4014 # endif 3922 4015 { 3923 4016 uint32_t uEAX, uEBX, uECX, uEDX; 3924 4017 3925 /* Permit user users override. */4018 /* Permit the user and/or the OS specfic bits to force async mode. */ 3926 4019 if (supdrvOSGetForcedAsyncTscMode(pDevExt)) 3927 4020 return SUPGIPMODE_ASYNC_TSC; 4021 4022 /** @todo perform supdrvDetermineAsyncTsc here! */ 3928 4023 3929 4024 /* Check for "AuthenticAMD" */ … … 3934 4029 && uEDX == X86_CPUID_VENDOR_AMD_EDX) 3935 4030 { 4031 /** @todo This is probably wrong. TscInvariant doesn't seem to mean that RdTSC returns the 4032 * value everywhere, but rather that the rate is supposed to be the same. */ 3936 4033 /* Check for APM support and that TscInvariant is cleared. */ 3937 4034 ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX); … … 3945 4042 } 3946 4043 } 3947 #endif3948 4044 return SUPGIPMODE_SYNC_TSC; 3949 4045 }
Note:
See TracChangeset
for help on using the changeset viewer.