/* **********************************************************
 * Copyright 1998 VMware, Inc.  All rights reserved. -- VMware Confidential
 * **********************************************************/

/*
 *
 * vm_basic_types.h -- 
 *
 *    basic data types.
 */

 
#ifndef _VM_BASIC_TYPES_H_
#define _VM_BASIC_TYPES_H_

#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMM
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"

/* STRICT ANSI means the Xserver build and X defines Bool differently. */
#ifndef __STRICT_ANSI__
typedef char           Bool;
#endif

#ifndef FALSE
#define FALSE          0
#endif

#ifndef TRUE
#define TRUE           1
#endif

/*
 * Macros __i386__ and __ia64 are intrinsically defined by GCC
 */
#ifdef __i386__
#define VM_I386
#endif

#ifdef __ia64__
#define VM_IA64
#endif

#ifdef __x86_64__
#define MODULE_X86_64
#define VM_I386
#endif

#ifdef _WIN64
#define MODULE_X86_64
#define __x86_64__
#endif

#ifdef _WIN32
/* safe assumption for a while */
#define VM_I386
#endif

#if defined VM_I386 && defined VM_IA64
#error "Only one CPU platform is allowed."
#endif

#ifdef _MSC_VER
typedef unsigned __int64 uint64;
typedef signed __int64 int64;

#pragma warning (3 :4505) // unreferenced local function
#pragma warning (disable :4018) // signed/unsigned mismatch
#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied
#pragma warning (disable :4305) // truncation from 'const int' to 'short'
#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char'
#if !defined VMX86_DEVEL // XXX until we clean up all the code -- edward
#pragma warning (disable :4133) // incompatible types - from 'struct VM *' to 'int *'
#pragma warning (disable :4047) // differs in levels of indirection
#endif
#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning (disable :4142) // benign redefinition of type

#elif __GNUC__
/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
#if defined(VM_IA64) || defined(MODULE_X86_64)
typedef unsigned long uint64;
typedef long int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif
#endif
#else
#error - Need compiler define for int64/uint64
#endif

typedef unsigned int       uint32;
typedef unsigned short     uint16;
typedef unsigned char      uint8;

typedef int       int32;
typedef short     int16;
typedef char      int8;

/*
 * FreeBSD (for the tools build) unconditionally defines these in
 * sys/inttypes.h so don't redefine them if this file has already
 * been included. [greg]
 */

#ifdef __FreeBSD__
#include <sys/inttypes.h>
#endif
#if !defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_)
#   if !defined(__intptr_t_defined) && !defined(intptr_t) 
#      define __intptr_t_defined
#      define intptr_t  intptr_t
#      ifdef VM_I386
#         ifdef MODULE_X86_64
             typedef int64     intptr_t;
#         else
             typedef int32     intptr_t;
#         endif
#      endif

#      ifdef VM_IA64
          typedef int64     intptr_t;
#      endif
#   endif

#   ifndef _STDINT_H
#      ifdef VM_I386
#         ifdef MODULE_X86_64
             typedef uint64    uintptr_t;
#         else
             typedef uint32    uintptr_t;
#         endif
#      endif

#      ifdef VM_IA64
          typedef uint64    uintptr_t;
#      endif
#   endif 
#endif

/*
 * Time
 * XXX These should be cleaned up.  -- edward
 */

typedef int64 VmTimeType;          /* Time in microseconds */
typedef int64 VmTimeRealClock;     /* Real clock kept in microseconds */
typedef int64 VmTimeVirtualClock;  /* Virtual Clock kept in CPU cycles */

/*
 * Printf format for 64-bit number.  Use it like this:
 *    printf("%"FMT64"d\n", big);
 */

#ifdef _MSC_VER
#define FMT64   "I64"
#elif __GNUC__
#define FMT64   "L"
#else
#error - Need compiler define for FMT64
#endif

/*
 * Suffix for 64-bit constants.  Use it like this:
 *    CONST64(0x7fffffffffffffff) for signed or 
 *    CONST64U(0x7fffffffffffffff) for unsigned.
 */

#ifdef _MSC_VER
#define CONST64(c) c##I64
#define CONST64U(c) c##uI64
#elif __GNUC__
#define CONST64(c) c##LL
#define CONST64U(c) c##uLL
#else
#error - Need compiler define for CONST64
#endif


typedef uintptr_t VA;
typedef uintptr_t VPN;

typedef uintptr_t PA;
typedef uintptr_t PPN;

/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
typedef uint64    BA;
#endif
typedef uint32    BPN;
typedef uint32    PageNum;

/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
typedef uint64     MA;
typedef uintptr_t  MPN;
#endif

/*
 * On 64 bit platform, address and page number types are default
 * to 64 bit. When we need to represent a 32 bit address, we use
 * types defined below.
 *
 * On 32 bit platform, the following types are the same as the
 * default types.
 */
typedef uint32 VA32;
typedef uint32 VPN32;
typedef uint32 PA32;
typedef uint32 PPN32;
typedef uint32 MA32;
typedef uint32 MPN32;
typedef int32  intptr32;
typedef uint32 uintptr32;

#define MAX_PPN     ((PPN)0x00ffffff)   /* Maximal observable PPN value. */
#define INVALID_PPN ((PPN)-1)

#define INVALID_BPN  ((BPN) 0x3fffffff) /* BPNs don't use the high two bits. */
#define INVALID_MPN ((MPN)-1)
#define INVALID_LPN ((LPN)-1)
#define INVALID_VPN ((VPN)-1)
#define INVALID_PAGENUM ((PageNum)-1)

#define EXTERN        extern
#define CONST         const

#ifdef _MSC_VER
#ifndef INLINE
#define INLINE        __inline
#endif
#else
#ifndef INLINE
#define INLINE        inline
#endif
#endif


#if defined(WIN32) && !defined(VMX86_NO_THREADS)
#define THREADSPECIFIC _declspec(thread) 
#else
#define THREADSPECIFIC
#endif


/*
 * Consider the following reasons functions are inlined:
 *
 *  1) inlined for performance reasons
 *  2) inlined because it's a single-use function
 *
 * Functions which meet only condition 2 should be marked with this
 * inline macro; It is not critical to be inlined (but there is a
 * code-space & runtime savings by doing so), so when other callers
 * are added the inline-ness should be removed.
 */

#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
/*
 * Starting at version 3.3, gcc does not always inline functions marked
 * 'inline' (it depends on their size). To force gcc to do so, one must use the
 * extra __always_inline__ attribute.
 */
#   define INLINE_SINGLE_CALLER INLINE __attribute__((__always_inline__))
#   if    defined(MONITOR) \
       && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
#      warning Verify INLINE_SINGLE_CALLER '__always_inline__' attribute (did \
             monitor size change?)
#   endif
#else
#   define INLINE_SINGLE_CALLER INLINE
#endif


/*
 * Attributes placed on function declarations to tell the compiler
 * that the function never returns.
 */

#ifdef _MSC_VER
#define NORETURN __declspec(noreturn)
#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 9)
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN
#endif

/*
 * GCC 3.2 inline asm needs the + constraint for input/ouput memory operands.
 * Older GCCs don't know about it --hpreg
 */

#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
#   define VM_ASM_PLUS 1
#else
#   define VM_ASM_PLUS 0
#endif

/*
 * Branch prediction hints:
 *     LIKELY(exp)   - Expression exp is likely TRUE.
 *     UNLIKELY(exp) - Expression exp is likely FALSE.
 *   Usage example:
 *        if (LIKELY(excCode == EXC_NONE)) {
 *               or
 *        if (UNLIKELY(REAL_MODE(vc))) {
 * 
 * We know how to predict branches on gcc3 and later (hopefully), 
 * all others we don't so we do nothing. 
 */

#if (__GNUC__ >= 3) 
/* 
 * gcc3 uses __builtin_expect() to inform the compiler of an expected value. 
 * We use this to inform the static branch predictor. The '!!' in LIKELY 
 * will convert any !=0 to a 1. 
 */ 
#define LIKELY(_exp)     __builtin_expect(!!(_exp), 1)
#define UNLIKELY(_exp)   __builtin_expect((_exp), 0) 
#else
#define LIKELY(_exp)      (_exp)
#define UNLIKELY(_exp)    (_exp)
#endif

/*
 * GCC's argument checking for printf-like functions
 * This is conditional until we have replaced all `"%x", void *'
 * with `"0x%08x", (uint32) void *'. Note that %p prints different things
 * on different platforms.  Argument checking is enabled for the
 * vmkernel, which has already been cleansed.
 *
 * fmtPos is the position of the format string argument, beginning at 1
 * varPos is the position of the variable argument, beginning at 1
 */

#if defined(__GNUC__)
# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
#else
# define PRINTF_DECL(fmtPos, varPos)
#endif

/*
 * UNUSED_PARAM should surround the parameter name and type declaration,
 * e.g. "int MyFunction(int var1, UNUSED_PARAM(int var2))"
 *
 */

#if defined(__GNUC__)
# define UNUSED_PARAM(_parm) _parm  __attribute__((__unused__))
#else
# define UNUSED_PARAM(_parm) _parm
#endif

/*
 * Once upon a time, this was used to silence compiler warnings that
 * get generated when the compiler thinks that a function returns
 * when it is marked noreturn.  Don't do it.  Use NOT_REACHED().
 */

#define INFINITE_LOOP()           do { } while (1)


/*
 * Global error codes. Currently used internally, but may be exported
 * to customers one day, like VM_E_XXX in vmcontrol_constants.h
 */

typedef enum VMwareStatus {
   VMWARE_STATUS_SUCCESS,  /* success */
   VMWARE_STATUS_ERROR,    /* generic error */
   VMWARE_STATUS_NOMEM,    /* generic memory allocation error */
   VMWARE_STATUS_INSUFFICIENT_RESOURCES, /* internal or system resource limit exceeded */
   VMWARE_STATUS_INVALID_ARGS  /* invalid arguments */
} VMwareStatus;

#define VMWARE_SUCCESS(s) ((s) == VMWARE_STATUS_SUCCESS)


typedef enum DiskMode {
   DISK_MODE_PERSISTENT = 1,
   DISK_MODE_NONPERSISTENT,
   DISK_MODE_CREATE_REDO,
   DISK_MODE_APPEND_REDO,
   DISK_MODE_INDEPENDENT_PERSISTENT,
   DISK_MODE_INDEPENDENT_NONPERSISTENT
} DiskMode;


/*
 * On FreeBSD (for the tools build), size_t is typedef'd if _BSD_SIZE_T_
 * is defined. Use the same logic here so we don't define it twice. [greg]
 */
#ifdef __FreeBSD__
#   ifdef _BSD_SIZE_T_
#      undef _BSD_SIZE_T_
#      ifdef VM_I386
#         ifdef MODULE_X86_64
             typedef uint64 size_t;
#         else
             typedef uint32 size_t;
#         endif
#      endif /* VM_I386 */

#      ifdef VM_IA64 
             typedef uint64 size_t;
#      endif
#   endif
#else
#   ifndef _SIZE_T
#      define _SIZE_T
#      ifdef VM_I386
#         ifdef MODULE_X86_64
             typedef uint64 size_t;
#         else
             typedef uint32 size_t;
#         endif
#      endif /* VM_I386 */

#      ifdef VM_IA64 
             typedef uint64 size_t;
#      endif
#   endif
#endif


#endif
