From: VMware, Inc <> Date: Wed, 20 Jan 2010 21:22:41 +0000 (-0800) Subject: Internal branch sync. Included in this change: X-Git-Tag: 2010.01.19-226760~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7495c0ccf45f188859dac3853770aab129cd4104;p=thirdparty%2Fopen-vm-tools.git Internal branch sync. Included in this change: . Fix an issue where only image data would be retrieved from the clipboard, instead of both image and text data. . Changes in shared code that don't affect open-vm-tools functionality. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/dnd/dndClipboard.c b/open-vm-tools/lib/dnd/dndClipboard.c index 7d3069e1c..0d36862d9 100644 --- a/open-vm-tools/lib/dnd/dndClipboard.c +++ b/open-vm-tools/lib/dnd/dndClipboard.c @@ -244,6 +244,13 @@ CPClipboard_SetItem(CPClipboard *clip, // IN/OUT: the clipboard { CPClipItem *item; void *newBuf = NULL; + /* + * Image, rtf and text may be put into a clipboard at same time, and total + * size may be more than limit. Image data will be first dropped, then + * rtf data. + */ + DND_CPFORMAT filterList[] = {CPFORMAT_IMG_PNG, CPFORMAT_RTF, CPFORMAT_TEXT}; + int filterIndex = 0; ASSERT(clip); @@ -259,31 +266,6 @@ CPClipboard_SetItem(CPClipboard *clip, // IN/OUT: the clipboard return FALSE; } - if (CPFORMAT_RTF == fmt) { - size_t textSize = clip->items[CPFormatToIndex(CPFORMAT_TEXT)].size; - if ((textSize + size) >= CPCLIPITEM_MAX_SIZE_V3) { - /* - * If both CPFORMAT_TEXT and CPFORMAT_RTF are availabe but total - * size is over limit, only keep CPFORMAT_TEXT. - */ - return TRUE; - } - } - - if (CPFORMAT_TEXT == fmt) { - size_t rtfSize = clip->items[CPFormatToIndex(CPFORMAT_RTF)].size; - if ((rtfSize + size) >= CPCLIPITEM_MAX_SIZE_V3) { - /* - * If both CPFORMAT_TEXT and CPFORMAT_RTF are availabe but total - * size is over limit, remove data for CPFORMAT_RTF and add data - * for CPFORMAT_TEXT. - */ - if (!CPClipboard_ClearItem(clip, CPFORMAT_RTF)) { - return FALSE; - } - } - } - item = &clip->items[CPFormatToIndex(fmt)]; if (clipitem) { @@ -298,6 +280,15 @@ CPClipboard_SetItem(CPClipboard *clip, // IN/OUT: the clipboard item->size = size; item->exists = TRUE; + /* Drop some data if total size is more than limit. */ + while (CPClipboard_GetTotalSize(clip) >= CPCLIPITEM_MAX_SIZE_V3 && + filterIndex < ARRAYSIZE(filterList)) { + if (!CPClipboard_ClearItem(clip, filterList[filterIndex])) { + return FALSE; + } + filterIndex++; + } + return TRUE; } @@ -448,6 +439,40 @@ CPClipboard_IsEmpty(const CPClipboard *clip) // IN: the clipboard } +/* + *---------------------------------------------------------------------------- + * + * CPClipboard_GetTotalSize -- + * + * Get total buffer size of the clipboard. + * + * Results: + * Total buffer size of the clipboard. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------------- + */ + +size_t +CPClipboard_GetTotalSize(const CPClipboard *clip) // IN: the clipboard +{ + unsigned int i = 0; + size_t totalSize = 0; + + ASSERT(clip); + + for (i = CPFORMAT_MIN; i < CPFORMAT_MAX; ++i) { + if (clip->items[CPFormatToIndex(i)].exists && + clip->items[CPFormatToIndex(i)].size > 0) { + totalSize += clip->items[CPFormatToIndex(i)].size; + } + } + return totalSize; +} + + /* *---------------------------------------------------------------------------- * diff --git a/open-vm-tools/lib/include/dndClipboard.h b/open-vm-tools/lib/include/dndClipboard.h index d7098bb42..9fa390cfd 100644 --- a/open-vm-tools/lib/include/dndClipboard.h +++ b/open-vm-tools/lib/include/dndClipboard.h @@ -105,6 +105,7 @@ Bool CPClipboard_GetItem(const CPClipboard *clip, DND_CPFORMAT fmt, void **buf, size_t *size); Bool CPClipboard_ItemExists(const CPClipboard *clip, DND_CPFORMAT fmt); Bool CPClipboard_IsEmpty(const CPClipboard *clip); +size_t CPClipboard_GetTotalSize(const CPClipboard *clip); Bool CPClipboard_Copy(CPClipboard *dest, const CPClipboard *src); Bool CPClipboard_Serialize(const CPClipboard *clip, DynBuf *buf); Bool CPClipboard_Unserialize(CPClipboard *clip, void *buf, size_t len); diff --git a/open-vm-tools/lib/include/guest_os.h b/open-vm-tools/lib/include/guest_os.h index 82613f382..cd767f85f 100644 --- a/open-vm-tools/lib/include/guest_os.h +++ b/open-vm-tools/lib/include/guest_os.h @@ -86,6 +86,7 @@ typedef enum GuestOSType { GUEST_OS_WINSEVEN_64 = GUEST_OS_BASE + 48, // Windows 7 GUEST_OS_WIN2008R2 = GUEST_OS_BASE + 49, // Server 2008 R2 GUEST_OS_WIN2008R2_64 = GUEST_OS_BASE + 50, // Server 2008 R2 + GUEST_OS_ECOMSTATION = GUEST_OS_BASE + 51, // OS/2 variant } GuestOSType; @@ -164,6 +165,8 @@ typedef enum GuestOSFamilyType { BS(SOLARIS10_64) | BS(FREEBSD_64) | \ ALLDARWIN64 | BS(OTHER_64) | BS(VMKERNEL)) +#define ALLOS2 (BS(OS2) | BS(ECOMSTATION)) + /* * These constants are generated by GuestInfoGetOSName which is in @@ -235,6 +238,7 @@ typedef enum GuestOSFamilyType { #define STR_OS_UNITEDLINUX "UnitedLinux" #define STR_OS_VALINUX "VALinux" #define STR_OS_YELLOW_DOG "Yellow Dog" +#define STR_OS_ECOMSTATION "eComStation" /* Windows */ #define STR_OS_WIN_31 "win31" diff --git a/open-vm-tools/lib/include/hostinfo.h b/open-vm-tools/lib/include/hostinfo.h index 024fced60..1586961bd 100644 --- a/open-vm-tools/lib/include/hostinfo.h +++ b/open-vm-tools/lib/include/hostinfo.h @@ -20,7 +20,7 @@ * hostinfo.h -- * * Interface to host-specific information functions - * + * */ #if !defined(_HOSTINFO_H_) @@ -130,6 +130,7 @@ typedef struct { extern uint32 Hostinfo_NumCPUs(void); +extern char *Hostinfo_GetCpuidStr(void); extern Bool Hostinfo_GetCpuid(HostinfoCpuIdInfo *info); #if defined(VMX86_SERVER) @@ -180,7 +181,7 @@ OS_TYPE Hostinfo_GetOSType(void); OS_DETAIL_TYPE Hostinfo_GetOSDetailType(void); Bool Hostinfo_GetPCFrequency(uint64 *pcHz); -Bool Hostinfo_GetMhzOfProcessor(int32 processorNumber, +Bool Hostinfo_GetMhzOfProcessor(int32 processorNumber, uint32 *currentMhz, uint32 *maxMhz); uint64 Hostinfo_SystemIdleTime(void); Bool Hostinfo_GetAllCpuid(CPUIDQuery *query); diff --git a/open-vm-tools/lib/include/vix.h b/open-vm-tools/lib/include/vix.h index 0398141c5..9b826ff9b 100644 --- a/open-vm-tools/lib/include/vix.h +++ b/open-vm-tools/lib/include/vix.h @@ -318,6 +318,7 @@ enum { VIX_E_WRAPPER_SERVICEPROVIDER_NOT_FOUND = 22003, VIX_E_WRAPPER_PLAYER_NOT_INSTALLED = 22004, VIX_E_WRAPPER_RUNTIME_NOT_INSTALLED = 22005, + VIX_E_WRAPPER_MULTIPLE_SERVICEPROVIDERS = 22006, /* FuseMnt errors*/ VIX_E_MNTAPI_MOUNTPT_NOT_FOUND = 24000, @@ -369,6 +370,20 @@ enum { VIX_E_MNTAPI_CREATE_PARTITIONTABLE_ERROR = 24320, VIX_E_MNTAPI_OPEN_FAILURE = 24321, VIX_E_MNTAPI_VOLUME_NOT_WRITABLE = 24322, + + /* Network Errors */ + VIX_E_NET_HTTP_UNSUPPORTED_PROTOCOL = 30001, + VIX_E_NET_HTTP_URL_MALFORMAT = 30003, + VIX_E_NET_HTTP_COULDNT_RESOLVE_PROXY = 30005, + VIX_E_NET_HTTP_COULDNT_RESOLVE_HOST = 30006, + VIX_E_NET_HTTP_COULDNT_CONNECT = 30007, + VIX_E_NET_HTTP_HTTP_RETURNED_ERROR = 30022, + VIX_E_NET_HTTP_OPERATION_TIMEDOUT = 30028, + VIX_E_NET_HTTP_SSL_CONNECT_ERROR = 30035, + VIX_E_NET_HTTP_TOO_MANY_REDIRECTS = 30047, + VIX_E_NET_HTTP_TRANSFER = 30200, + VIX_E_NET_HTTP_SSL_SECURITY = 30201, + VIX_E_NET_HTTP_GENERIC = 30202, }; // {{ End VIX_ERROR }} diff --git a/open-vm-tools/lib/lock/mutexInt.h b/open-vm-tools/lib/lock/mutexInt.h new file mode 100644 index 000000000..d2eeca215 --- /dev/null +++ b/open-vm-tools/lib/lock/mutexInt.h @@ -0,0 +1,254 @@ +/********************************************************* + * Copyright (C) 2000 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation version 2.1 and no later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + *********************************************************/ + +/* + * mutexInt.h -- + * + * Internal interface for the Mutex module + */ + +#ifndef _MUTEXINT_H_ +#define _MUTEXINT_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_VMMEXT +#define INCLUDE_ALLOW_VMCORE +#include "includeCheck.h" + +#include "mutex.h" +#if defined VMX86_VMX || defined VMM || defined MONITOR_APP +#include "usercall.h" +#endif + +/* + * NOTE to Windows users on semaphores: + * + * The semaphores that are implemented here are for the implementation + * of the MX_* primitives. They are used in a specialized way such that + * they serve the purpose of the MX_* implementation. The Windows + * implementation uses Windows Event objects and not Semaphore objects + * for implementation reasons. + * The Windows driver needs to access the Windows Event object during a + * module call. The object lookup function in the driver can lookup up + * Windows Event objects and not Windows Semaphore objects. Since Windows + * Event objects have the proper semantics, they are used to implement + * our semaphores. + * + * Since the monitor is always compiled on Linux, SEMA_INVALID_HANDLE + * really has to be the same value on all hosts. This nicely matches + * Windows' INVALID_HANDLE_VALUE, which is asserted in MXSemaphoreInit(). + */ + +#if defined VMX86_VMX || defined VMM || defined MONITOR_APP +typedef struct MXSemaphoreRPC { + RPCBlock rpc; + uint32 _pad0; + MXSemaphore sema; +} MXSemaphoreRPC; +#endif + +void MXSemaphoreInit(MXSemaphore *sema); +void MXSemaphoreInvalidate(MXSemaphore *sema); +void MXSemaphoreDestroy(MXSemaphore *sema); +void MXSemaphoreWait(MXSemaphore *sema, MX_Rank rank); +Bool MXSemaphoreWaitTimeout(MXSemaphore *sema, MX_Rank rank, int maxWaitUS); +Bool MXSemaphoreTryWait(MXSemaphore *sema); +void MXSemaphoreSignal(MXSemaphore *sema); + + +/* + * Locks + */ + +#define MX_LOCK_ID_NULL MX_MAX_LOCKS + +/* + * Each lock has an affiliate (per-lock) data structure. This data structure + * is kept separately from the lock itself to make it visible across the + * vmx/vmm divide, regardless of the visibility of the lock. + */ + +typedef struct MXPerLock { + MXSemaphore sema; /* Semaphore for blocking. */ + Atomic_uint32 isActive; /* Whether this "perLock" is active. */ +#if MX_FAT_LOCKS != 0 + uint32 pad; /* Pad for windows (align next field). */ + uint64 lockCount; /* #times this lock was acquired. */ + uint64 lockCountBlocking; /* #times acquisition was blocking. */ + MX_Rank rank; /* Rank of this lock; immutable. */ + MX_LockID next; /* Next held lock on per-thread list. */ + char name[MX_MAX_NAME_LEN]; /* Zero-terminated name for lock. */ +#endif +} MXPerLock; + + +/* + * Condition variables. We use only CAS and the host binary semaphore + * primitive. + * + * We keep a list of waiters, who are awakened in FIFO order. Because it + * is impossible to append to the end of a singly-linked list using only + * CAS, we use an unusual representation of the queue waiters. + * + * The queue is represented as two lists, "head" and "tail." The first item in + * the queue appears in "head". Subsequent items in the queue may follow in + * "head". If "tail" is non-empty, it contains a list of queue items logically + * behind all those in "head", and _in reversed order_. I.e., if "tail" isn't + * empty, its _first_ item is the _last_ item in the queue. + * + * This way, entering an item into the queue always boils down to the simple, + * CAS-implementable operation of prepending an item to the head of a linked + * list: the "head" list if the queue is empty, and the "tail" list otherwise. + */ + +#define MX_LIST_INVAL ((MXCVLink)-1U) + +/* + * Support for locks and condition variables + */ + +typedef struct MXPerThread { +#if MX_FAT_LOCKS != 0 + uint64 lockCount; /* #times this thread acquired a lock. */ + uint64 lockCountBlocking; /* #times acquisition was blocking. */ + MX_LockID first; /* First lock held by this thread. */ + uint32 partiallyLocked; /* Locks partially acquired by thread. */ +#endif + MXSemaphore sema; /* sema for CV blocking */ + MXCVLink cvLink; /* forward link for CV wait queue */ + Bool initialized; + uint8 _pad[6]; +} MXPerThread; + +typedef struct MXState { +#if defined(__i386__) || defined(__x86_64__) + uint64 startTSC; /* Init-time TSC. */ +#endif + Atomic_uint32 numLocks; /* Number of active locks. */ + unsigned spinLimit; /* Spin limit before blocking. */ + Bool doneInit; /* To make init idempotent. */ + uint32 pad; /* Make windows and linux agree. */ + MXPerLock perLock[MX_MAX_LOCKS]; /* Indexed by lock id. */ + MXPerThread perThread[VTHREAD_MAX_THREADS]; /* Indexed by thread id. */ +} MXState; + +#ifdef VMM +EXTERN SHARED_PER_VM MXState mxState; +#else +extern MXState *mxState; /* Module state; in shared area. */ +#endif + +static INLINE MXState * +GetMXState(void) +{ +#ifdef VMM + return &mxState; +#else + return mxState; +#endif +} + +/* + * Iterate "lid" over all locks held by "tid", which *must* be the + * current thread to avoid races. + */ + +#define FOR_ALL_LOCKS_HELD(tid, lid) \ + for (lid = GetPerThread(tid)->first; \ + lid != MX_LOCK_ID_NULL; \ + lid = GetPerLock(lid)->next) + +#define FOR_ALL_ACTIVE_LOCKS(lid) \ + for (lid = 0; lid < MX_MAX_LOCKS; lid++) \ + if (Atomic_Read(&GetPerLock(lid)->isActive)) + +static INLINE MXPerLock * +GetPerLock(MX_LockID lid) // IN: +{ + ASSERT(lid < MX_MAX_LOCKS); + + return GetMXState()->perLock + lid; +} + +static INLINE MXPerThread * +GetPerThread(VThreadID tid) // IN: +{ + return GetMXState()->perThread + tid; +} + +static INLINE MXPerThread * +GetMyPerThread(void) +{ + return GetPerThread(VThread_CurID()); +} + +static INLINE MXSemaHandle +MXSemaphoreGetSemaHandle(MXSemaphore *sema) // IN: +{ +#ifdef _WIN32 + MXSemaHandle *ph = (MXSemaHandle *) &sema->waitHandle; + + return *ph; +#else + return sema->waitHandle; +#endif +} + +#ifdef _WIN32 + +static INLINE void +MXSemaphoreSetSemaHandle(MXSemaphore *sema, // IN/OUT: + MXSemaHandle h) // IN: +{ + MXSemaHandle *ph = (MXSemaHandle *) &sema->waitHandle; + *ph = h; + +#ifndef _WIN64 + /* + * This handle might be seen by a 64-bit vmmon, so make sure the + * upper 32-bits are set correctly. + */ + + if (h == (MXSemaHandle) VMW_INVALID_HANDLE) { + sema->signalHandle = (int) VMW_INVALID_HANDLE; + } else { + sema->signalHandle = 0; + } +#endif // _WIN64 +} + +#endif // _WIN32 + +#ifdef USERLEVEL +void MXInvalidatePerThread(VThreadID tid); +#endif + + +/* + * Lock stats + */ + +#if MX_STATS_LEVEL > 2 +void MXIncLockCount(void); +#else +#define MXIncLockCount() +#endif + +#define MX_WAITTIMEOUT 1000 // milliseconds + +#endif // ifndef _MUTEXINT_H_ diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index 81b7ad876..75442cea1 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -16,12 +16,23 @@ * *********************************************************/ - #include "vmware.h" #include "str.h" #include "util.h" #include "userlock.h" #include "ulInt.h" +#include "mutexInt.h" + +#if defined(VMX86_DEBUG) +#define MXUSER_MAX_LOCKS_PER_THREAD 24 + +typedef struct { + uint32 lockNum; + MXUserHeader *lockArray[MXUSER_MAX_LOCKS_PER_THREAD]; +} MXUserPerThread; + +static MXUserPerThread mxUserPerThread[VTHREAD_MAX_THREADS]; +#endif /* @@ -50,6 +61,123 @@ MXUserIDHack(void) } +#if defined(VMX86_DEBUG) +/* + *----------------------------------------------------------------------------- + * + * MXUserAcquireRankCheck + * + * Perform rank checking for lock acquisition. + * + * Results: + * A panic on rank violation. + * + * Side effects: + * Manifold. + * + *----------------------------------------------------------------------------- + */ + +void +MXUserAcquireRankCheck(MXUserHeader *header) // IN: +{ + VThreadID tid = (*MXUserThreadCurID)(); + MXUserPerThread *perThread = &mxUserPerThread[tid]; + + /* Hack until VThread_CurID is fixed */ + if ((tid == VTHREAD_INVALID_ID) || (tid == VTHREAD_OTHER_ID)) { + return; + } + + ASSERT_NOT_IMPLEMENTED(perThread->lockNum < MXUSER_MAX_LOCKS_PER_THREAD); + + perThread->lockArray[perThread->lockNum++] = header; + + if (header->lockRank != RANK_UNRANKED) { + uint32 i; + MX_Rank maxRank; + + /* Check MX locks when they are present */ + maxRank = (mxState) ? MX_CurrentRank() : RANK_UNRANKED; + + for (i = 0; i < perThread->lockNum; i++) { + maxRank = MAX(perThread->lockArray[i]->lockRank, maxRank); + } + + if (header->lockRank <= maxRank) { + Warning("%s: lock rank violation by thread %s\n", __FUNCTION__, + VThread_CurName()); + Warning("%s: locks held:\n", __FUNCTION__); + + for (i = 0; i < perThread->lockNum; i++) { + MXUserHeader *hdr = perThread->lockArray[i]; + + Warning("\tMXUser lock %s (@%p) rank %d\n", hdr->lockName, hdr, + hdr->lockRank); + } + + if (mxState) { + MX_LockID lid; + + FOR_ALL_LOCKS_HELD(tid, lid) { + MXPerLock *perLock = GetPerLock(lid); + + Warning("\tMX lock %s (@%u) rank %d\n", perLock->name, + lid, perLock->rank); + } + } + + MXUserDumpAndPanic(header, "%s: rank violation\n", __FUNCTION__); + } + } +} + + +/* + *----------------------------------------------------------------------------- + * + * MXUserReleaseRankCheck + * + * Perform rank checking for lock release. + * + * Results: + * A panic. + * + * Side effects: + * Manifold. + * + *----------------------------------------------------------------------------- + */ + +void +MXUserReleaseRankCheck(MXUserHeader *header) // IN: +{ + uint32 i; + VThreadID tid = (*MXUserThreadCurID)(); + MXUserPerThread *perThread = &mxUserPerThread[tid]; + + /* Hack until VThread_CurID is fixed */ + if ((tid == VTHREAD_INVALID_ID) || (tid == VTHREAD_OTHER_ID)) { + return; + } + + for (i = 0; i < perThread->lockNum; i++) { + if (perThread->lockArray[i] == header) { + break; + } + } + + ASSERT_NOT_IMPLEMENTED(i < perThread->lockNum); // better find it + + if (i < perThread->lockNum - 1) { + perThread->lockArray[i] = perThread->lockArray[perThread->lockNum - 1]; + } + + perThread->lockNum--; +} +#endif + + /* *----------------------------------------------------------------------------- * diff --git a/open-vm-tools/lib/lock/ulAcquire.c b/open-vm-tools/lib/lock/ulAcquire.c index 02450d970..e95edea49 100644 --- a/open-vm-tools/lib/lock/ulAcquire.c +++ b/open-vm-tools/lib/lock/ulAcquire.c @@ -16,7 +16,6 @@ * *********************************************************/ - #include "vmware.h" #include "userlock.h" #include "ulInt.h" @@ -43,11 +42,13 @@ MXUser_AcquireExclLock(MXUserExclLock *lock) // IN/OUT: { ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE); + MXUserAcquireRankCheck(&lock->lockHeader); + MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress()); if (MXRecLockCount(&lock->lockRecursive) > 1) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Acquire on an acquired exclusive lock", + "%s: Acquire on an acquired exclusive lock\n", __FUNCTION__); } } @@ -76,5 +77,7 @@ MXUser_AcquireRecLock(MXUserRecLock *lock) // IN/OUT: { ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE); + MXUserAcquireRankCheck(&lock->lockHeader); + MXRecLockAcquire(&lock->lockRecursive, GetReturnAddress()); } diff --git a/open-vm-tools/lib/lock/ulCreate.c b/open-vm-tools/lib/lock/ulCreate.c index 6f95acca2..27b03cdb3 100644 --- a/open-vm-tools/lib/lock/ulCreate.c +++ b/open-vm-tools/lib/lock/ulCreate.c @@ -16,7 +16,6 @@ * *********************************************************/ - #include "vmware.h" #include "str.h" #include "util.h" @@ -134,14 +133,16 @@ MXUserDumpRecLock(MXUserHeader *header) // IN: Warning("\tname %s\n", lock->lockHeader.lockName); Warning("\trank %d\n", lock->lockHeader.lockRank); - Warning("\tcount %u\n", lock->lockRecursive.lockCount); + if (lock->lockVmm == NULL) { + Warning("\tcount %u\n", lock->lockRecursive.lockCount); #if defined(VMX86_DEBUG) - Warning("\tcaller %p\n", lock->lockRecursive.lockCaller); - Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID); + Warning("\tcaller %p\n", lock->lockRecursive.lockCaller); + Warning("\tVThreadID %d\n", (int) lock->lockRecursive.lockVThreadID); #endif - - Warning("\tlockVmm %p\n", lock->lockVmm); + } else { + Warning("\tlockVmm %p\n", lock->lockVmm); + } } diff --git a/open-vm-tools/lib/lock/ulDestroy.c b/open-vm-tools/lib/lock/ulDestroy.c index c2b57799c..af2d23ca9 100644 --- a/open-vm-tools/lib/lock/ulDestroy.c +++ b/open-vm-tools/lib/lock/ulDestroy.c @@ -44,7 +44,7 @@ MXUser_DestroyExclLock(MXUserExclLock *lock) // IN: if (MXRecLockCount(&lock->lockRecursive) > 0) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Destroy of an acquired exclusive lock", + "%s: Destroy of an acquired exclusive lock\n", __FUNCTION__); } @@ -79,7 +79,7 @@ MXUser_DestroyRecLock(MXUserRecLock *lock) // IN: if (MXRecLockCount(&lock->lockRecursive) > 0) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Destroy of an acquired recursive lock", + "%s: Destroy of an acquired recursive lock\n", __FUNCTION__); } diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index 15fdd61f7..fb8326710 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -422,4 +422,21 @@ Bool MXUserIsAllUnlocked(const MXUserRWLock *lock); void MXUserDumpAndPanic(MXUserHeader *header, const char *fmt, ...); + +#if defined(VMX86_DEBUG) +void MXUserAcquireRankCheck(MXUserHeader *header); +void MXUserReleaseRankCheck(MXUserHeader *header); +#else +static INLINE void +MXUserAcquireRankCheck(MXUserHeader *header) +{ + return; +} + +static INLINE void +MXUserReleaseRankCheck(MXUserHeader *header) +{ + return; +} +#endif #endif diff --git a/open-vm-tools/lib/lock/ulRWPosix.c b/open-vm-tools/lib/lock/ulRWPosix.c index ee316e85b..10cfbc9e6 100644 --- a/open-vm-tools/lib/lock/ulRWPosix.c +++ b/open-vm-tools/lib/lock/ulRWPosix.c @@ -95,8 +95,6 @@ MXUser_CreateRWLock(const char *userName, // IN: char *properName; MXUserRWLock *lock; - ASSERT(rank == RANK_UNRANKED); // NOT FOR LONG - lock = Util_SafeCalloc(1, sizeof(*lock)); if (userName == NULL) { @@ -162,19 +160,21 @@ MXUser_AcquireForRead(MXUserRWLock *lock) // IN/OUT: ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE); + MXUserAcquireRankCheck(&lock->lockHeader); + #if defined(PTHREAD_RWLOCK_INITIALIZER) err = pthread_rwlock_rdlock(&lock->lockReadWrite); if (err == 0) { if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: AcquireForRead after AcquireForRead", + "%s: AcquireForRead after AcquireForRead\n", __FUNCTION__); } } else { - MXUserDumpAndPanic(&lock->lockHeader, "%s: %s", - (err == EDEADLK) ? "Deadlock detected (%d)" : - "Internal error (%d)", + MXUserDumpAndPanic(&lock->lockHeader, + (err == EDEADLK) ? "%s: Deadlock detected (%d)\n" : + "%s: Internal error (%d)\n", __FUNCTION__, err); } #else @@ -183,12 +183,12 @@ MXUser_AcquireForRead(MXUserRWLock *lock) // IN/OUT: if (lock->lockTaken[self] != RW_UNLOCKED) { if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: AcquireForRead after AcquireForRead" - __FUNCTION__, self); + "%s: AcquireForRead after AcquireForRead\n" + __FUNCTION__); } else { MXUserDumpAndPanic(&lock->lockHeader, - "%s: AcquireForRead after AcquireForWrite" - __FUNCTION__, self); + "%s: AcquireForRead after AcquireForWrite\n" + __FUNCTION__); } } @@ -226,13 +226,15 @@ MXUser_AcquireForWrite(MXUserRWLock *lock) // IN/OUT: ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE); + MXUserAcquireRankCheck(&lock->lockHeader); + #if defined(PTHREAD_RWLOCK_INITIALIZER) err = pthread_rwlock_wrlock(&lock->lockReadWrite); if (err != 0) { - MXUserDumpAndPanic(&lock->lockHeader, "%s: %s", - (err == EDEADLK) ? "Deadlock detected (%d)" : - "Internal error (%d)", + MXUserDumpAndPanic(&lock->lockHeader, + (err == EDEADLK) ? "%s: Deadlock detected (%d)\n" : + "%s: Internal error (%d)\n", __FUNCTION__, err); } #else @@ -241,11 +243,11 @@ MXUser_AcquireForWrite(MXUserRWLock *lock) // IN/OUT: if (lock->lockTaken[self] != RW_UNLOCKED) { if (lock->lockTaken[self] == RW_LOCKED_FOR_READ) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: AcquireForRead after AcquireForWrite" + "%s: AcquireForRead after AcquireForWrite\n" __FUNCTION__); } else { MXUserDumpAndPanic(&lock->lockHeader, - "%s: AcquireForWrite after AcquireForWrite" + "%s: AcquireForWrite after AcquireForWrite\n" __FUNCTION__); } } @@ -283,10 +285,12 @@ MXUser_ReleaseRWLock(MXUserRWLock *lock) // IN/OUT: if (myState == RW_UNLOCKED) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Release of read-lock not by owner (%d)", + "%s: Release of read-lock not by owner (%d)\n", __FUNCTION__, self); } + MXUserReleaseRankCheck(&lock->lockHeader); + lock->lockTaken[self] = RW_UNLOCKED; #if defined(PTHREAD_RWLOCK_INITIALIZER) @@ -326,7 +330,7 @@ MXUser_DestroyRWLock(MXUserRWLock *lock) // IN: if (!MXUserIsAllUnlocked(lock)) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Destroy on read-lock while still acquired", + "%s: Destroy on read-lock while still acquired\n", __FUNCTION__); } diff --git a/open-vm-tools/lib/lock/ulRelease.c b/open-vm-tools/lib/lock/ulRelease.c index ae9fa95a7..a4be89378 100644 --- a/open-vm-tools/lib/lock/ulRelease.c +++ b/open-vm-tools/lib/lock/ulRelease.c @@ -45,15 +45,17 @@ MXUser_ReleaseExclLock(MXUserExclLock *lock) // IN/OUT: if (!MXRecLockIsOwner(&lock->lockRecursive)) { if (MXRecLockCount(&lock->lockRecursive) == 0) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Release of an unacquired exclusive lock", + "%s: Release of an unacquired exclusive lock\n", __FUNCTION__); } else { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Release of owned exclusive lock", + "%s: Release of owned exclusive lock\n", __FUNCTION__); } } + MXUserReleaseRankCheck(&lock->lockHeader); + MXRecLockRelease(&lock->lockRecursive); } @@ -82,14 +84,16 @@ MXUser_ReleaseRecLock(MXUserRecLock *lock) // IN/OUT: if (!MXRecLockIsOwner(&lock->lockRecursive)) { if (MXRecLockCount(&lock->lockRecursive) == 0) { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Release of an unacquired recursive lock", + "%s: Release of an unacquired recursive lock\n", __FUNCTION__); } else { MXUserDumpAndPanic(&lock->lockHeader, - "%s: Release of owned recursive lock", + "%s: Release of owned recursive lock\n", __FUNCTION__); } } + MXUserReleaseRankCheck(&lock->lockHeader); + MXRecLockRelease(&lock->lockRecursive); } diff --git a/open-vm-tools/lib/lock/ulTryAcquire.c b/open-vm-tools/lib/lock/ulTryAcquire.c index 8379d69cb..cadfd5022 100644 --- a/open-vm-tools/lib/lock/ulTryAcquire.c +++ b/open-vm-tools/lib/lock/ulTryAcquire.c @@ -16,7 +16,6 @@ * *********************************************************/ - #include "vmware.h" #include "userlock.h" #include "ulInt.h" @@ -48,10 +47,14 @@ MXUser_TryAcquireExclLock(MXUserExclLock *lock) // IN/OUT: success = MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress()); - if (success && (MXRecLockCount(&lock->lockRecursive) > 1)) { - MXUserDumpAndPanic(&lock->lockHeader, - "%s: Acquire on an acquired exclusive lock", - __FUNCTION__); + if (success) { + if (MXRecLockCount(&lock->lockRecursive) > 1) { + MXUserDumpAndPanic(&lock->lockHeader, + "%s: Acquire on an acquired exclusive lock\n", + __FUNCTION__); + } + + MXUserAcquireRankCheck(&lock->lockHeader); } return success; @@ -80,7 +83,15 @@ MXUser_TryAcquireExclLock(MXUserExclLock *lock) // IN/OUT: Bool MXUser_TryAcquireRecLock(MXUserRecLock *lock) // IN/OUT: { + Bool success; + ASSERT(lock->lockHeader.lockSignature == USERLOCK_SIGNATURE); - return MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress()); + success = MXRecLockTryAcquire(&lock->lockRecursive, GetReturnAddress()); + + if (success) { + MXUserAcquireRankCheck(&lock->lockHeader); + } + + return success; } diff --git a/open-vm-tools/lib/misc/hostinfo.c b/open-vm-tools/lib/misc/hostinfo.c index 39e2c82f4..c175dad5d 100644 --- a/open-vm-tools/lib/misc/hostinfo.c +++ b/open-vm-tools/lib/misc/hostinfo.c @@ -31,6 +31,8 @@ #endif #include "hostinfo.h" #include "util.h" +#include "str.h" +#include "dynbuf.h" #define LOGLEVEL_MODULE hostinfo #include "loglevel_user.h" @@ -102,6 +104,111 @@ HostInfoGetAMDCPUCount(CPUIDSummary *cpuid, // IN #endif // defined(__i386__) || defined(__x86_64__) +/* + *----------------------------------------------------------------------------- + * + * HostInfoGetCpuidStrSection -- + * + * Append a section (either low or high) of CPUID as a string in DynBuf. + * E.g. + * 00000000:00000005756E65476C65746E49656E69- + * 00000001:00000F4A000208000000649DBFEBFBFF- + * or + * 80000000:80000008000000000000000000000000- + * 80000001:00000000000000000000000120100000- + * 80000008:00003024000000000000000000000000- + * + * The returned eax of args[0] is used to determine the upper bound for + * the following input arguments. And the input args should be in ascending + * order. + * + * Results: + * None. The string will be appended in buf. + * + * Side effect: + * None + * + *----------------------------------------------------------------------------- + */ + +static void +HostInfoGetCpuidStrSection(const uint32 args[], // IN: input eax arguments + const size_t args_size, // IN: size of the argument array + DynBuf *buf) // IN/OUT: result string in DynBuf +{ + static const char format[] = "%08X:%08X%08X%08X%08X-"; + CPUIDRegs reg; + uint32 max_arg; + char temp[64]; + int i; + + __GET_CPUID(args[0], ®); + max_arg = reg.eax; + if (max_arg < args[0]) { + Warning(LGPFX" No CPUID information available. Based = %08X.\n", args[0]); + return; + } + DynBuf_Append(buf, temp, + Str_Sprintf(temp, sizeof temp, format, args[0], reg.eax, reg.ebx, reg.ecx, reg.edx)); + + for (i = 1; i < args_size && args[i] <= max_arg; i++) { + ASSERT(args[i] > args[i - 1]); // Ascending order. + __GET_CPUID(args[i], ®); + + DynBuf_Append(buf, temp, + Str_Sprintf(temp, sizeof temp, format, args[i], reg.eax, reg.ebx, reg.ecx, reg.edx)); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * Hostinfo_GetCpuidStr -- + * + * Get the basic and extended CPUID as a string. E.g. + * 00000000:00000005756E65476C65746E49656E69- + * 00000001:00000F4A000208000000649DBFEBFBFF- + * 80000000:80000008000000000000000000000000- + * 80000001:00000000000000000000000120100000- + * 80000008:00003024000000000000000000000000 + * + * If the extended CPUID is not available, only returns the basic CPUID. + * + * Results: + * The CPUID string if the processor supports the CPUID instruction and this + * is a processor we recognize. It should never fail, since it would at least + * return leaf 0. Caller needs to free the returned string. + * + * Side effect: + * None + * + *----------------------------------------------------------------------------- + */ + +char * +Hostinfo_GetCpuidStr(void) +{ + static const uint32 basic_args[] = {0x0, 0x1, 0xa}; + static const uint32 extended_args[] = {0x80000000, 0x80000001, 0x80000008}; + DynBuf buf; + char *result; + + DynBuf_Init(&buf); + + HostInfoGetCpuidStrSection(basic_args, ARRAYSIZE(basic_args), &buf); + HostInfoGetCpuidStrSection(extended_args, ARRAYSIZE(extended_args), &buf); + + // Trim buffer and set NULL character to replace last '-'. + DynBuf_Trim(&buf); + result = (char*)DynBuf_Get(&buf); + ASSERT(result && result[0]); // We should at least get result from eax = 0x0. + result[DynBuf_GetSize(&buf) - 1] = '\0'; + + return DynBuf_Detach(&buf); +} + + /* *----------------------------------------------------------------------------- * @@ -217,7 +324,7 @@ Hostinfo_GetCpuid(HostinfoCpuIdInfo *info) // OUT Log(LGPFX" hyperthreading disabled, setting number of threads per core " "to 1.\n"); numThreadsPerCore = 1; - } + } #endif info->numPhysCPUs = info->numLogCPUs / (numCoresPerPCPU * @@ -349,7 +456,7 @@ Hostinfo_TouchXen(void) CPUIDRegs regs; uint32 name[4]; - /* + /* * PV mode: ud2a "xen" cpuid (faults on native hardware). * (Only Linux can run PV, so skip others here). * Since PV cannot trap CPUID, this is a Xen hook. @@ -376,7 +483,7 @@ Hostinfo_TouchXen(void) /* Passed checks. But native and anything non-Xen would #UD before here. */ NOT_TESTED(); Log("Xen detected but hypervisor unrecognized (Xen variant?)\n"); - Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n", + Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx); #endif