~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201207201942

« back to all changes in this revision

Viewing changes to modules/linux/vsock/include/vm_basic_asm_x86_64.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-03-20 10:19:00 UTC
  • mfrom: (1.1.4 upstream) (2.4.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090320101900-1o604camiubq2de8
Tags: 2009.03.18-154848-2
Correcting patch system depends (Closes: #520493).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License as published by the
 
6
 * Free Software Foundation version 2 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
11
 * for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * vm_basic_asm_x86_64.h
 
21
 *
 
22
 *      Basic x86_64 asm macros.
 
23
 */
 
24
 
 
25
#ifndef _VM_BASIC_ASM_X86_64_H_
 
26
#define _VM_BASIC_ASM_X86_64_H_
 
27
 
 
28
#define INCLUDE_ALLOW_USERLEVEL
 
29
#define INCLUDE_ALLOW_VMMEXT
 
30
#define INCLUDE_ALLOW_MODULE
 
31
#define INCLUDE_ALLOW_VMMON
 
32
#define INCLUDE_ALLOW_VMK_MODULE
 
33
#define INCLUDE_ALLOW_VMKERNEL
 
34
#define INCLUDE_ALLOW_DISTRIBUTE
 
35
#define INCLUDE_ALLOW_VMCORE
 
36
#define INCLUDE_ALLOW_VMNIXMOD
 
37
#include "includeCheck.h"
 
38
 
 
39
#ifndef VM_X86_64
 
40
#error "This file is x86-64 only!"
 
41
#endif
 
42
 
 
43
#ifdef _MSC_VER
 
44
 
 
45
#ifdef __cplusplus
 
46
extern "C" {
 
47
#endif
 
48
uint64 _umul128(uint64 multiplier, uint64 multiplicand, 
 
49
                uint64 *highProduct);
 
50
int64 _mul128(int64 multiplier, int64 multiplicand, 
 
51
              int64 *highProduct);
 
52
uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
 
53
#ifdef __cplusplus
 
54
}
 
55
#endif
 
56
 
 
57
#pragma intrinsic(_umul128, _mul128, __shiftright128)
 
58
 
 
59
#endif // _MSC_VER
 
60
 
 
61
/*
 
62
 * FXSAVE/FXRSTOR
 
63
 *     save/restore SIMD/MMX fpu state
 
64
 *
 
65
 * The pointer passed in must be 16-byte aligned.
 
66
 *
 
67
 * Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
 
68
 * processors unconditionally save the exception pointer state (instruction
 
69
 * ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
 
70
 * work correctly for Intel processors.
 
71
 *
 
72
 * AMD processors only save the exception pointer state if ES=1. This leads to a
 
73
 * security hole whereby one process/VM can inspect the state of another process
 
74
 * VM. The AMD recommended workaround involves clobbering the exception pointer
 
75
 * state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
 
76
 * FXSAVE_ES1 will only save the exception pointer state for AMD processors if
 
77
 * ES=1.
 
78
 *
 
79
 * The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
 
80
 * fxrstor, on both AMD Opteron and Intel Core CPUs.
 
81
 */
 
82
#if defined(__GNUC__)
 
83
 
 
84
static INLINE void 
 
85
FXSAVE_ES1(uint8 *save)
 
86
{
 
87
   __asm__ __volatile__ ("fxsaveq %0  \n" : "=m" (*save) : : "memory");
 
88
}
 
89
 
 
90
static INLINE void 
 
91
FXSAVE_COMPAT_ES1(uint8 *save)
 
92
{
 
93
   __asm__ __volatile__ ("fxsave %0  \n" : "=m" (*save) : : "memory");
 
94
}
 
95
 
 
96
static INLINE void 
 
97
FXRSTOR_ES1(const uint8 *load)
 
98
{
 
99
   __asm__ __volatile__ ("fxrstorq %0 \n" : : "m" (*load) : "memory");
 
100
}
 
101
 
 
102
static INLINE void 
 
103
FXRSTOR_COMPAT_ES1(const uint8 *load)
 
104
{
 
105
   __asm__ __volatile__ ("fxrstor %0 \n" : : "m" (*load) : "memory");
 
106
}
 
107
 
 
108
static INLINE void 
 
109
FXRSTOR_AMD_ES0(const uint8 *load)
 
110
{
 
111
   uint64 dummy = 0;
 
112
      
 
113
   __asm__ __volatile__ 
 
114
       ("fnstsw  %%ax    \n"     // Grab x87 ES bit
 
115
        "bt      $7,%%ax \n"     // Test ES bit
 
116
        "jnc     1f      \n"     // Jump if ES=0
 
117
        "fnclex          \n"     // ES=1. Clear it so fild doesn't trap
 
118
        "1:              \n"
 
119
        "ffree   %%st(7) \n"     // Clear tag bit - avoid poss. stack overflow
 
120
        "fildl   %0      \n"     // Dummy Load from "safe address" changes all
 
121
                                 // x87 exception pointers.
 
122
        "fxrstorq %1 \n"
 
123
        :
 
124
        : "m" (dummy), "m" (*load)
 
125
        : "ax", "memory");
 
126
}
 
127
 
 
128
#endif /* __GNUC__ */
 
129
 
 
130
 
 
131
/*
 
132
 *-----------------------------------------------------------------------------
 
133
 *
 
134
 * Mul64x3264 --
 
135
 *
 
136
 *    Unsigned integer by fixed point multiplication:
 
137
 *       result = multiplicand * multiplier >> shift
 
138
 * 
 
139
 *       Unsigned 64-bit integer multiplicand.
 
140
 *       Unsigned 32-bit fixed point multiplier, represented as
 
141
 *         multiplier >> shift, where shift < 64.
 
142
 *       Unsigned 64-bit integer product.
 
143
 *
 
144
 * Implementation:
 
145
 *    Multiply 64x64 bits to yield a full 128-bit product.
 
146
 *    Shift result in RDX:RAX right by "shift".
 
147
 *    Return the low-order 64 bits of the above.
 
148
 *
 
149
 * Result:
 
150
 *    Product
 
151
 *
 
152
 *-----------------------------------------------------------------------------
 
153
 */
 
154
 
 
155
#if defined(__GNUC__)
 
156
 
 
157
static INLINE uint64
 
158
Mul64x3264(uint64 multiplicand,
 
159
           uint32 multiplier,
 
160
           uint32 shift)
 
161
{
 
162
   uint64 result, dummy;
 
163
   const uint64 multiplier64 = multiplier;
 
164
 
 
165
   __asm__("mulq    %3      \n\t"
 
166
           "shrdq   %1, %0  \n\t"
 
167
           : "=a" (result),
 
168
             "=d" (dummy)
 
169
           : "0"  (multiplier64),
 
170
             "rm" (multiplicand),
 
171
         "c"  (shift)
 
172
           : "cc");
 
173
   return result;
 
174
}
 
175
 
 
176
#elif defined(_MSC_VER)
 
177
 
 
178
static INLINE uint64
 
179
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
 
180
{
 
181
   uint64 tmplo, tmphi;
 
182
   tmplo = _umul128(multiplicand, multiplier, &tmphi);
 
183
   return __shiftright128(tmplo, tmphi, (uint8) shift);
 
184
}
 
185
 
 
186
#endif
 
187
 
 
188
/*
 
189
 *-----------------------------------------------------------------------------
 
190
 *
 
191
 * Muls64x32s64 --
 
192
 *
 
193
 *    Signed integer by fixed point multiplication:
 
194
 *       result = multiplicand * multiplier >> shift
 
195
 * 
 
196
 *       Signed 64-bit integer multiplicand.
 
197
 *       Unsigned 32-bit fixed point multiplier, represented as
 
198
 *         multiplier >> shift, where shift < 64.
 
199
 *       Signed 64-bit integer product.
 
200
 *
 
201
 * Implementation:
 
202
 *    Multiply 64x64 bits to yield a full 128-bit product.
 
203
 *    Shift result in RDX:RAX right by "shift".
 
204
 *    Return the low-order 64 bits of the above.
 
205
 *
 
206
 *    Note: using an unsigned shift instruction is correct because
 
207
 *    shift < 64 and we return only the low 64 bits of the shifted
 
208
 *    result.
 
209
 *
 
210
 * Result:
 
211
 *    Product
 
212
 *
 
213
 *-----------------------------------------------------------------------------
 
214
 */
 
215
 
 
216
#if defined(__GNUC__)
 
217
 
 
218
static inline int64
 
219
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
 
220
{
 
221
   int64 result, dummy;
 
222
   const int64 multiplier64 = multiplier;
 
223
 
 
224
   __asm__("imulq   %3      \n\t"
 
225
       "shrdq   %1, %0  \n\t"
 
226
       : "=a" (result),
 
227
         "=d" (dummy)
 
228
       : "0"  (multiplier64),
 
229
         "rm" (multiplicand),
 
230
         "c"  (shift)
 
231
       : "cc");
 
232
   return result;
 
233
}
 
234
 
 
235
#elif defined(_MSC_VER)
 
236
 
 
237
static INLINE int64
 
238
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
 
239
{
 
240
   int64 tmplo, tmphi;
 
241
   tmplo = _mul128(multiplicand, multiplier, &tmphi);
 
242
   return __shiftright128(tmplo, tmphi, (uint8) shift);
 
243
}
 
244
 
 
245
#endif
 
246
 
 
247
 
 
248
#if defined(__GNUC__)
 
249
 
 
250
static INLINE void *
 
251
uint64set(void *dst, uint64 val, uint64 count)
 
252
{
 
253
   int dummy0;
 
254
   int dummy1;
 
255
   __asm__ __volatile__("\t"
 
256
                        "cld"            "\n\t"
 
257
                        "rep ; stosq"    "\n"
 
258
                        : "=c" (dummy0), "=D" (dummy1)
 
259
                        : "0" (count), "1" (dst), "a" (val)
 
260
                        : "memory", "cc");
 
261
   return dst;
 
262
}
 
263
 
 
264
#endif
 
265
 
 
266
/*
 
267
 *-----------------------------------------------------------------------------
 
268
 *
 
269
 * Div643232 --
 
270
 *
 
271
 *    Unsigned integer division:
 
272
 *       The dividend is 64-bit wide
 
273
 *       The divisor  is 32-bit wide
 
274
 *       The quotient is 32-bit wide
 
275
 *
 
276
 *    Use this function if you are certain that the quotient will fit in 32 bits,
 
277
 *    If that is not the case, a #DE exception was generated in 32-bit version,
 
278
 *    but not in this 64-bit version. So please be careful.
 
279
 *
 
280
 * Results:
 
281
 *    Quotient and remainder
 
282
 *
 
283
 * Side effects:
 
284
 *    None
 
285
 *
 
286
 *-----------------------------------------------------------------------------
 
287
 */
 
288
 
 
289
#if defined(__GNUC__) || defined(_MSC_VER)
 
290
 
 
291
static INLINE void
 
292
Div643232(uint64 dividend,   // IN
 
293
          uint32 divisor,    // IN
 
294
          uint32 *quotient,  // OUT
 
295
          uint32 *remainder) // OUT
 
296
{
 
297
   *quotient = (uint32)(dividend / divisor);
 
298
   *remainder = (uint32)(dividend % divisor);
 
299
}
 
300
 
 
301
#endif
 
302
 
 
303
/*
 
304
 *-----------------------------------------------------------------------------
 
305
 *
 
306
 * Div643264 --
 
307
 *
 
308
 *    Unsigned integer division:
 
309
 *       The dividend is 64-bit wide
 
310
 *       The divisor  is 32-bit wide
 
311
 *       The quotient is 64-bit wide
 
312
 *
 
313
 * Results:
 
314
 *    Quotient and remainder
 
315
 *
 
316
 * Side effects:
 
317
 *    None
 
318
 *
 
319
 *-----------------------------------------------------------------------------
 
320
 */
 
321
 
 
322
#if defined(__GNUC__)
 
323
 
 
324
static INLINE void
 
325
Div643264(uint64 dividend,   // IN
 
326
          uint32 divisor,    // IN
 
327
          uint64 *quotient,  // OUT
 
328
          uint32 *remainder) // OUT
 
329
{
 
330
   *quotient = dividend / divisor;
 
331
   *remainder = dividend % divisor;
 
332
}
 
333
 
 
334
#endif
 
335
 
 
336
#endif // _VM_BASIC_ASM_X86_64_H_