/src/xen/xen/arch/x86/x86_emulate/private.h
Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | | /****************************************************************************** |
3 | | * private.h - interface between x86_emulate.c and its helpers |
4 | | * |
5 | | * Copyright (c) 2005-2007 Keir Fraser |
6 | | * Copyright (c) 2005-2007 XenSource Inc. |
7 | | */ |
8 | | |
9 | | #ifndef X86_EMULATE_PRIVATE_H |
10 | | #define X86_EMULATE_PRIVATE_H |
11 | | |
12 | | #ifdef __XEN__ |
13 | | |
14 | | # include <xen/bug.h> |
15 | | # include <xen/kernel.h> |
16 | | |
17 | | # include <asm/cpu-user-regs.h> |
18 | | # include <asm/endbr.h> |
19 | | # include <asm/msr-index.h> |
20 | | # include <asm/stubs.h> |
21 | | # include <asm/x86-vendors.h> |
22 | | # include <asm/x86_emulate.h> |
23 | | |
24 | | # undef BUG /* Make sure it's not used anywhere here. */ |
25 | | void BUG(void); |
26 | | |
27 | | # ifndef CONFIG_HVM |
28 | | # define X86EMUL_NO_FPU |
29 | | # define X86EMUL_NO_MMX |
30 | | # define X86EMUL_NO_SIMD |
31 | | # endif |
32 | | |
33 | | #else /* !__XEN__ */ |
34 | | # include "x86-emulate.h" |
35 | | #endif |
36 | | |
37 | | #ifdef __i386__ |
38 | | # define mode_64bit() false |
39 | | # define r(name) e ## name |
40 | | # define PTR_POISON NULL /* 32-bit builds are for user-space, so NULL is OK. */ |
41 | | #else |
42 | 1.28M | # define mode_64bit() (ctxt->addr_size == 64) |
43 | 384k | # define r(name) r ## name |
44 | 1.42M | # define PTR_POISON ((void *)0x8086000000008086UL) /* non-canonical */ |
45 | | #endif |
46 | | |
47 | | /* Operand sizes: 8-bit operands or specified/overridden size. */ |
48 | 447k | #define ByteOp (1<<0) /* 8-bit operands. */ |
49 | | /* Destination operand type. */ |
50 | 309k | #define DstNone (0<<1) /* No destination operand. */ |
51 | 1.60k | #define DstImplicit (0<<1) /* Destination operand is implicit in the opcode. */ |
52 | 3.52k | #define DstBitBase (1<<1) /* Memory operand, bit string. */ |
53 | 118k | #define DstReg (2<<1) /* Register operand. */ |
54 | 13.6k | #define DstEax DstReg /* Register EAX (aka DstReg with no ModRM) */ |
55 | 146k | #define DstMem (3<<1) /* Memory operand. */ |
56 | 506k | #define DstMask (3<<1) |
57 | | /* Source operand type. */ |
58 | 235k | #define SrcNone (0<<3) /* No source operand. */ |
59 | 1.80k | #define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */ |
60 | 64.9k | #define SrcReg (1<<3) /* Register operand. */ |
61 | | #define SrcEax SrcReg /* Register EAX (aka SrcReg with no ModRM) */ |
62 | 196k | #define SrcMem (2<<3) /* Memory operand. */ |
63 | 39.6k | #define SrcMem16 (3<<3) /* Memory operand (16-bit). */ |
64 | 47.6k | #define SrcImm (4<<3) /* Immediate operand. */ |
65 | 78.7k | #define SrcImmByte (5<<3) /* 8-bit sign-extended immediate operand. */ |
66 | 2.42k | #define SrcImm16 (6<<3) /* 16-bit zero-extended immediate operand. */ |
67 | 969k | #define SrcMask (7<<3) |
68 | | /* Generic ModRM decode. */ |
69 | 1.26M | #define ModRM (1<<6) |
70 | | /* vSIB addressing mode (0f38 extension opcodes only), aliasing ModRM. */ |
71 | 438 | #define vSIB (1<<6) |
72 | | /* Destination is only written; never read. */ |
73 | 177k | #define Mov (1<<7) |
74 | | /* VEX/EVEX (SIMD only): 2nd source operand unused (must be all ones) */ |
75 | 22.1k | #define TwoOp Mov |
76 | | /* All operands are implicit in the opcode. */ |
77 | 10 | #define ImplicitOps (DstImplicit|SrcImplicit) |
78 | | |
79 | | typedef uint8_t opcode_desc_t; |
80 | | |
81 | | enum disp8scale { |
82 | | /* Values 0 ... 4 are explicit sizes. */ |
83 | | d8s_bw = 5, |
84 | | d8s_dq, |
85 | | /* EVEX.W ignored outside of 64-bit mode */ |
86 | | d8s_dq64, |
87 | | /* |
88 | | * All further values must strictly be last and in the order |
89 | | * given so that arithmetic on the values works. |
90 | | */ |
91 | | d8s_vl, |
92 | | d8s_vl_by_2, |
93 | | d8s_vl_by_4, |
94 | | d8s_vl_by_8, |
95 | | }; |
96 | | typedef uint8_t disp8scale_t; |
97 | | |
98 | | /* Type, address-of, and value of an instruction's operand. */ |
99 | | struct operand { |
100 | | enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; |
101 | | unsigned int bytes; |
102 | | |
103 | | /* Operand value. */ |
104 | | unsigned long val; |
105 | | |
106 | | /* Original operand value. */ |
107 | | unsigned long orig_val; |
108 | | |
109 | | /* OP_REG: Pointer to register field. */ |
110 | | unsigned long *reg; |
111 | | |
112 | | /* OP_MEM: Segment and offset. */ |
113 | | struct { |
114 | | enum x86_segment seg; |
115 | | unsigned long off; |
116 | | } mem; |
117 | | }; |
118 | | |
119 | | #if defined(__x86_64__) |
120 | 86.4k | #define REX_PREFIX 0x40 |
121 | 38.9k | #define REX_B 0x01 |
122 | 1.98k | #define REX_X 0x02 |
123 | 9.82k | #define REX_R 0x04 |
124 | 474k | #define REX_W 0x08 |
125 | | #elif defined(__i386__) |
126 | | #define REX_PREFIX 0 |
127 | | #define REX_B 0 |
128 | | #define REX_X 0 |
129 | | #define REX_R 0 |
130 | | #define REX_W 0 |
131 | | #endif |
132 | | |
133 | | enum simd_opsize { |
134 | | simd_none, |
135 | | |
136 | | /* |
137 | | * Ordinary packed integers: |
138 | | * - 64 bits without prefix 66 (MMX) |
139 | | * - 128 bits with prefix 66 (SSEn) |
140 | | * - 128/256/512 bits depending on VEX.L/EVEX.LR (AVX+) |
141 | | */ |
142 | | simd_packed_int, |
143 | | |
144 | | /* |
145 | | * Ordinary packed/scalar floating point: |
146 | | * - 128 bits without prefix or with prefix 66 (SSEn) |
147 | | * - 128/256/512 bits depending on VEX.L/EVEX.LR (AVX+) |
148 | | * - 32 bits with prefix F3 (scalar single) |
149 | | * - 64 bits with prefix F2 (scalar doubgle) |
150 | | */ |
151 | | simd_any_fp, |
152 | | |
153 | | /* |
154 | | * Packed floating point: |
155 | | * - 128 bits without prefix or with prefix 66 (SSEn) |
156 | | * - 128/256/512 bits depending on VEX.L/EVEX.LR (AVX+) |
157 | | */ |
158 | | simd_packed_fp, |
159 | | |
160 | | /* |
161 | | * Single precision packed/scalar floating point: |
162 | | * - 128 bits without prefix (SSEn) |
163 | | * - 128/256/512 bits depending on VEX.L/EVEX.LR (AVX+) |
164 | | * - 32 bits with prefix F3 (scalar) |
165 | | */ |
166 | | simd_single_fp, |
167 | | |
168 | | /* |
169 | | * Scalar floating point: |
170 | | * - 32 bits with low opcode bit clear (scalar single) |
171 | | * - 64 bits with low opcode bit set (scalar double) |
172 | | */ |
173 | | simd_scalar_opc, |
174 | | |
175 | | /* |
176 | | * Scalar floating point: |
177 | | * - 32/64 bits depending on VEX.W/EVEX.W |
178 | | */ |
179 | | simd_scalar_vexw, |
180 | | |
181 | | /* |
182 | | * 128 bits of integer or floating point data, with no further |
183 | | * formatting information, or with it encoded by EVEX.W. |
184 | | */ |
185 | | simd_128, |
186 | | |
187 | | /* |
188 | | * 256 bits of integer or floating point data, with formatting |
189 | | * encoded by EVEX.W. |
190 | | */ |
191 | | simd_256, |
192 | | |
193 | | /* Operand size encoded in non-standard way. */ |
194 | | simd_other |
195 | | }; |
196 | | typedef uint8_t simd_opsize_t; |
197 | | |
198 | 166k | #define vex_none 0 |
199 | | |
200 | | enum vex_opcx { |
201 | | vex_0f = vex_none + 1, |
202 | | vex_0f38, |
203 | | vex_0f3a, |
204 | | evex_map5 = 5, |
205 | | evex_map6, |
206 | | }; |
207 | | |
208 | | enum vex_pfx { |
209 | | vex_66 = vex_none + 1, |
210 | | vex_f3, |
211 | | vex_f2 |
212 | | }; |
213 | | |
214 | 19.9k | #define VEX_PREFIX_DOUBLE_MASK 0x1 |
215 | 29.3k | #define VEX_PREFIX_SCALAR_MASK 0x2 |
216 | | |
217 | | union vex { |
218 | | uint8_t raw[2]; |
219 | | struct { /* SDM names */ |
220 | | uint8_t opcx:5; /* mmmmm */ |
221 | | uint8_t b:1; /* B */ |
222 | | uint8_t x:1; /* X */ |
223 | | uint8_t r:1; /* R */ |
224 | | uint8_t pfx:2; /* pp */ |
225 | | uint8_t l:1; /* L */ |
226 | | uint8_t reg:4; /* vvvv */ |
227 | | uint8_t w:1; /* W */ |
228 | | }; |
229 | | }; |
230 | | |
231 | | union evex { |
232 | | uint8_t raw[3]; |
233 | | struct { /* SDM names */ |
234 | | uint8_t opcx:3; /* mmm */ |
235 | | uint8_t mbz:1; |
236 | | uint8_t R:1; /* R' */ |
237 | | uint8_t b:1; /* B */ |
238 | | uint8_t x:1; /* X */ |
239 | | uint8_t r:1; /* R */ |
240 | | uint8_t pfx:2; /* pp */ |
241 | | uint8_t mbs:1; |
242 | | uint8_t reg:4; /* vvvv */ |
243 | | uint8_t w:1; /* W */ |
244 | | uint8_t opmsk:3; /* aaa */ |
245 | | uint8_t RX:1; /* V' */ |
246 | | uint8_t brs:1; /* b */ |
247 | | uint8_t lr:2; /* L'L */ |
248 | | uint8_t z:1; /* z */ |
249 | | }; |
250 | | }; |
251 | | |
252 | | struct x86_emulate_state { |
253 | | unsigned int op_bytes, ad_bytes; |
254 | | |
255 | | enum { |
256 | | ext_none = vex_none, |
257 | | ext_0f = vex_0f, |
258 | | ext_0f38 = vex_0f38, |
259 | | ext_0f3a = vex_0f3a, |
260 | | ext_map5 = evex_map5, |
261 | | ext_map6 = evex_map6, |
262 | | /* |
263 | | * For XOP use values such that the respective instruction field |
264 | | * can be used without adjustment. |
265 | | */ |
266 | | ext_8f08 = 8, |
267 | | ext_8f09, |
268 | | ext_8f0a, |
269 | | } ext; |
270 | | enum { |
271 | | rmw_NONE, |
272 | | rmw_adc, |
273 | | rmw_add, |
274 | | rmw_and, |
275 | | rmw_btc, |
276 | | rmw_btr, |
277 | | rmw_bts, |
278 | | rmw_cmpccxadd, |
279 | | rmw_dec, |
280 | | rmw_inc, |
281 | | rmw_neg, |
282 | | rmw_not, |
283 | | rmw_or, |
284 | | rmw_rcl, |
285 | | rmw_rcr, |
286 | | rmw_rol, |
287 | | rmw_ror, |
288 | | rmw_sar, |
289 | | rmw_sbb, |
290 | | rmw_shl, |
291 | | rmw_shld, |
292 | | rmw_shr, |
293 | | rmw_shrd, |
294 | | rmw_sub, |
295 | | rmw_xadd, |
296 | | rmw_xchg, |
297 | | rmw_xor, |
298 | | } rmw; |
299 | | enum { |
300 | | blk_NONE, |
301 | | blk_enqcmd, |
302 | | #ifndef X86EMUL_NO_FPU |
303 | | blk_fld, /* FLDENV, FRSTOR */ |
304 | | blk_fst, /* FNSTENV, FNSAVE */ |
305 | | #endif |
306 | | #if !defined(X86EMUL_NO_FPU) || !defined(X86EMUL_NO_MMX) || \ |
307 | | !defined(X86EMUL_NO_SIMD) |
308 | | blk_fxrstor, |
309 | | blk_fxsave, |
310 | | #endif |
311 | | blk_movdir, |
312 | | } blk; |
313 | | uint8_t modrm, modrm_mod, modrm_reg, modrm_rm; |
314 | | uint8_t sib_index, sib_scale; |
315 | | uint8_t rex_prefix; |
316 | | bool lock_prefix; |
317 | | bool not_64bit; /* Instruction not available in 64bit. */ |
318 | | bool fpu_ctrl; /* Instruction is an FPU control one. */ |
319 | | bool fp16; /* Instruction has half-precision FP source operand. */ |
320 | | opcode_desc_t desc; |
321 | | union vex vex; |
322 | | union evex evex; |
323 | | enum simd_opsize simd_size; |
324 | | |
325 | | /* |
326 | | * Data operand effective address (usually computed from ModRM). |
327 | | * Default is a memory operand relative to segment DS. |
328 | | */ |
329 | | struct operand ea; |
330 | | |
331 | | /* Immediate operand values, if any. Use otherwise unused fields. */ |
332 | 60.3k | #define imm1 ea.val |
333 | 2.09k | #define imm2 ea.orig_val |
334 | | |
335 | | unsigned long ip; |
336 | | |
337 | | struct stub_exn *stub_exn; |
338 | | |
339 | | #ifndef NDEBUG |
340 | | /* |
341 | | * Track caller of x86_decode_insn() to spot missing as well as |
342 | | * premature calls to x86_emulate_free_state(). |
343 | | */ |
344 | | void *caller; |
345 | | #endif |
346 | | }; |
347 | | |
348 | | static inline void check_state(const struct x86_emulate_state *s) |
349 | 0 | { |
350 | 0 | #if defined(__XEN__) && !defined(NDEBUG) |
351 | 0 | ASSERT(s->caller); |
352 | 0 | #endif |
353 | 0 | } Unexecuted instantiation: x86-emulate.c:check_state Unexecuted instantiation: 0f01.c:check_state Unexecuted instantiation: 0fae.c:check_state Unexecuted instantiation: 0fc7.c:check_state Unexecuted instantiation: decode.c:check_state Unexecuted instantiation: fpu.c:check_state |
354 | | |
355 | | typedef union { |
356 | | uint64_t mmx; |
357 | | uint64_t __attribute__ ((aligned(16))) xmm[2]; |
358 | | uint64_t __attribute__ ((aligned(32))) ymm[4]; |
359 | | uint64_t __attribute__ ((aligned(64))) zmm[8]; |
360 | | uint32_t data32[16]; |
361 | | } mmval_t; |
362 | | |
363 | | struct x86_fxsr { |
364 | | uint16_t fcw; |
365 | | uint16_t fsw; |
366 | | uint8_t ftw, :8; |
367 | | uint16_t fop; |
368 | | union { |
369 | | struct { |
370 | | uint32_t offs; |
371 | | uint16_t sel, :16; |
372 | | }; |
373 | | uint64_t addr; |
374 | | } fip, fdp; |
375 | | uint32_t mxcsr; |
376 | | uint32_t mxcsr_mask; |
377 | | struct { |
378 | | uint8_t data[10]; |
379 | | uint16_t :16, :16, :16; |
380 | | } fpreg[8]; |
381 | | uint64_t __attribute__ ((aligned(16))) xmm[16][2]; |
382 | | uint64_t rsvd[6]; |
383 | | uint64_t avl[6]; |
384 | | }; |
385 | | |
386 | | #ifndef X86EMUL_NO_FPU |
387 | | struct x87_env16 { |
388 | | uint16_t fcw; |
389 | | uint16_t fsw; |
390 | | uint16_t ftw; |
391 | | union { |
392 | | struct { |
393 | | uint16_t fip_lo; |
394 | | uint16_t fop:11, :1, fip_hi:4; |
395 | | uint16_t fdp_lo; |
396 | | uint16_t :12, fdp_hi:4; |
397 | | } real; |
398 | | struct { |
399 | | uint16_t fip; |
400 | | uint16_t fcs; |
401 | | uint16_t fdp; |
402 | | uint16_t fds; |
403 | | } prot; |
404 | | } mode; |
405 | | }; |
406 | | |
407 | | struct x87_env32 { |
408 | | uint32_t fcw:16, :16; |
409 | | uint32_t fsw:16, :16; |
410 | | uint32_t ftw:16, :16; |
411 | | union { |
412 | | struct { |
413 | | /* some CPUs/FPUs also store the full FIP here */ |
414 | | uint32_t fip_lo:16, :16; |
415 | | uint32_t fop:11, :1, fip_hi:16, :4; |
416 | | /* some CPUs/FPUs also store the full FDP here */ |
417 | | uint32_t fdp_lo:16, :16; |
418 | | uint32_t :12, fdp_hi:16, :4; |
419 | | } real; |
420 | | struct { |
421 | | uint32_t fip; |
422 | | uint32_t fcs:16, fop:11, :5; |
423 | | uint32_t fdp; |
424 | | uint32_t fds:16, :16; |
425 | | } prot; |
426 | | } mode; |
427 | | }; |
428 | | #endif |
429 | | |
430 | | /* |
431 | | * Externally visible return codes from x86_emulate() are non-negative. |
432 | | * Use negative values for internal state change indicators from helpers |
433 | | * to the main function. |
434 | | */ |
435 | 132 | #define X86EMUL_rdtsc (-1) |
436 | | #define X86EMUL_stub_failure (-2) |
437 | | |
438 | | /* |
439 | | * These EFLAGS bits are restored from saved value during emulation, and |
440 | | * any changes are written back to the saved value after emulation. |
441 | | */ |
442 | 143k | #define EFLAGS_MASK (X86_EFLAGS_OF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \ |
443 | 143k | X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF) |
444 | | |
445 | | /* |
446 | | * These EFLAGS bits are modifiable (by POPF and IRET), possibly subject |
447 | | * to further CPL and IOPL constraints. |
448 | | */ |
449 | 2.16k | #define EFLAGS_MODIFIABLE (X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_RF | \ |
450 | 2.16k | X86_EFLAGS_NT | X86_EFLAGS_IOPL | X86_EFLAGS_DF | \ |
451 | 2.16k | X86_EFLAGS_IF | X86_EFLAGS_TF | EFLAGS_MASK) |
452 | | |
453 | 363k | #define truncate_word(ea, byte_width) \ |
454 | 363k | ({ unsigned long __ea = (ea); \ |
455 | 363k | unsigned int _width = (byte_width); \ |
456 | 363k | ((_width == sizeof(unsigned long)) ? __ea : \ |
457 | 363k | (__ea & ((1UL << (_width << 3)) - 1))); \ |
458 | 363k | }) |
459 | 316k | #define truncate_ea(ea) truncate_word((ea), ad_bytes) |
460 | | |
461 | 657k | #define fail_if(p) \ |
462 | 657k | do { \ |
463 | 657k | rc = (p) ? X86EMUL_UNHANDLEABLE : X86EMUL_OKAY; \ |
464 | 657k | if ( rc ) goto done; \ |
465 | 657k | } while (0) |
466 | | |
467 | 180k | #define EXPECT(p) \ |
468 | 180k | do { \ |
469 | 180k | if ( unlikely(!(p)) ) \ |
470 | 180k | { \ |
471 | 0 | ASSERT_UNREACHABLE(); \ |
472 | 0 | goto unhandleable; \ |
473 | 0 | } \ |
474 | 180k | } while (0) |
475 | | |
476 | | static inline int mkec(uint8_t e, int32_t ec, ...) |
477 | 3.53k | { |
478 | 3.53k | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; |
479 | 3.53k | } Line | Count | Source | 477 | 3.22k | { | 478 | 3.22k | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 3.22k | } |
Line | Count | Source | 477 | 163 | { | 478 | 163 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 163 | } |
Line | Count | Source | 477 | 38 | { | 478 | 38 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 38 | } |
Line | Count | Source | 477 | 6 | { | 478 | 6 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 6 | } |
Line | Count | Source | 477 | 64 | { | 478 | 64 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 64 | } |
Line | Count | Source | 477 | 39 | { | 478 | 39 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 39 | } |
|
480 | | |
481 | 3.62M | #define generate_exception_if(p, e, ec...) \ |
482 | 5.66M | ({ if ( (p) ) { \ |
483 | 3.53k | x86_emul_hw_exception(e, mkec(e, ##ec, 0), ctxt); \ |
484 | 3.53k | rc = X86EMUL_EXCEPTION; \ |
485 | 3.53k | goto done; \ |
486 | 3.53k | } \ |
487 | 287k | }) |
488 | | |
489 | 259 | #define generate_exception(e, ec...) generate_exception_if(true, e, ##ec) |
490 | | |
491 | | static inline bool |
492 | | in_realmode( |
493 | | struct x86_emulate_ctxt *ctxt, |
494 | | const struct x86_emulate_ops *ops) |
495 | 36.5k | { |
496 | 36.5k | unsigned long cr0; |
497 | 36.5k | int rc; |
498 | | |
499 | 36.5k | if ( ops->read_cr == NULL ) |
500 | 3.76k | return 0; |
501 | | |
502 | 32.7k | rc = ops->read_cr(0, &cr0, ctxt); |
503 | 32.7k | return (!rc && !(cr0 & X86_CR0_PE)); |
504 | 36.5k | } x86-emulate.c:in_realmode Line | Count | Source | 495 | 15.3k | { | 496 | 15.3k | unsigned long cr0; | 497 | 15.3k | int rc; | 498 | | | 499 | 15.3k | if ( ops->read_cr == NULL ) | 500 | 3.08k | return 0; | 501 | | | 502 | 12.2k | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 12.2k | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 15.3k | } |
Line | Count | Source | 495 | 778 | { | 496 | 778 | unsigned long cr0; | 497 | 778 | int rc; | 498 | | | 499 | 778 | if ( ops->read_cr == NULL ) | 500 | 221 | return 0; | 501 | | | 502 | 557 | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 557 | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 778 | } |
Unexecuted instantiation: 0fae.c:in_realmode Unexecuted instantiation: 0fc7.c:in_realmode Line | Count | Source | 495 | 20.4k | { | 496 | 20.4k | unsigned long cr0; | 497 | 20.4k | int rc; | 498 | | | 499 | 20.4k | if ( ops->read_cr == NULL ) | 500 | 462 | return 0; | 501 | | | 502 | 19.9k | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 19.9k | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 20.4k | } |
Unexecuted instantiation: fpu.c:in_realmode |
505 | | |
506 | | static inline bool |
507 | | in_protmode( |
508 | | struct x86_emulate_ctxt *ctxt, |
509 | | const struct x86_emulate_ops *ops) |
510 | 15.8k | { |
511 | 15.8k | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); |
512 | 15.8k | } x86-emulate.c:in_protmode Line | Count | Source | 510 | 15.0k | { | 511 | 15.0k | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); | 512 | 15.0k | } |
Line | Count | Source | 510 | 778 | { | 511 | 778 | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); | 512 | 778 | } |
Unexecuted instantiation: 0fae.c:in_protmode Unexecuted instantiation: 0fc7.c:in_protmode Unexecuted instantiation: decode.c:in_protmode Unexecuted instantiation: fpu.c:in_protmode |
513 | | |
514 | 4.44k | #define mode_ring0() ({ \ |
515 | 4.44k | int _cpl = x86emul_get_cpl(ctxt, ops); \ |
516 | 4.44k | fail_if(_cpl < 0); \ |
517 | 4.44k | (_cpl == 0); \ |
518 | 3.03k | }) |
519 | | |
520 | | static inline bool |
521 | | _amd_like(const struct cpu_policy *cp) |
522 | 20.3k | { |
523 | 20.3k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); |
524 | 20.3k | } Line | Count | Source | 522 | 16.1k | { | 523 | 16.1k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); | 524 | 16.1k | } |
Unexecuted instantiation: 0f01.c:_amd_like Unexecuted instantiation: 0fae.c:_amd_like Unexecuted instantiation: 0fc7.c:_amd_like Line | Count | Source | 522 | 4.14k | { | 523 | 4.14k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); | 524 | 4.14k | } |
Unexecuted instantiation: fpu.c:_amd_like |
525 | | |
526 | | static inline bool |
527 | | amd_like(const struct x86_emulate_ctxt *ctxt) |
528 | 16.0k | { |
529 | 16.0k | return _amd_like(ctxt->cpu_policy); |
530 | 16.0k | } Line | Count | Source | 528 | 11.8k | { | 529 | 11.8k | return _amd_like(ctxt->cpu_policy); | 530 | 11.8k | } |
Unexecuted instantiation: 0f01.c:amd_like Unexecuted instantiation: 0fae.c:amd_like Unexecuted instantiation: 0fc7.c:amd_like Line | Count | Source | 528 | 4.14k | { | 529 | 4.14k | return _amd_like(ctxt->cpu_policy); | 530 | 4.14k | } |
Unexecuted instantiation: fpu.c:amd_like |
531 | | |
532 | | #define vcpu_has_fpu() (ctxt->cpuid->basic.fpu) |
533 | | #define vcpu_has_sep() (ctxt->cpuid->basic.sep) |
534 | | #define vcpu_has_cx8() (ctxt->cpuid->basic.cx8) |
535 | | #define vcpu_has_cmov() (ctxt->cpuid->basic.cmov) |
536 | | #define vcpu_has_clflush() (ctxt->cpuid->basic.clflush) |
537 | | #define vcpu_has_mmx() (ctxt->cpuid->basic.mmx) |
538 | | #define vcpu_has_fxsr() (ctxt->cpuid->basic.fxsr) |
539 | | #define vcpu_has_sse() (ctxt->cpuid->basic.sse) |
540 | | #define vcpu_has_sse2() (ctxt->cpuid->basic.sse2) |
541 | | #define vcpu_has_sse3() (ctxt->cpuid->basic.sse3) |
542 | | #define vcpu_has_pclmulqdq() (ctxt->cpuid->basic.pclmulqdq) |
543 | | #define vcpu_has_ssse3() (ctxt->cpuid->basic.ssse3) |
544 | | #define vcpu_has_fma() (ctxt->cpuid->basic.fma) |
545 | | #define vcpu_has_cx16() (ctxt->cpuid->basic.cx16) |
546 | | #define vcpu_has_sse4_1() (ctxt->cpuid->basic.sse4_1) |
547 | | #define vcpu_has_sse4_2() (ctxt->cpuid->basic.sse4_2) |
548 | | #define vcpu_has_movbe() (ctxt->cpuid->basic.movbe) |
549 | | #define vcpu_has_popcnt() (ctxt->cpuid->basic.popcnt) |
550 | | #define vcpu_has_aesni() (ctxt->cpuid->basic.aesni) |
551 | | #define vcpu_has_avx() (ctxt->cpuid->basic.avx) |
552 | | #define vcpu_has_f16c() (ctxt->cpuid->basic.f16c) |
553 | | #define vcpu_has_rdrand() (ctxt->cpuid->basic.rdrand) |
554 | | |
555 | | #define vcpu_has_mmxext() (ctxt->cpuid->extd.mmxext || vcpu_has_sse()) |
556 | | #define vcpu_has_3dnow_ext() (ctxt->cpuid->extd._3dnowext) |
557 | | #define vcpu_has_3dnow() (ctxt->cpuid->extd._3dnow) |
558 | | #define vcpu_has_lahf_lm() (ctxt->cpuid->extd.lahf_lm) |
559 | 1 | #define vcpu_has_cr8_legacy() (ctxt->cpuid->extd.cr8_legacy) |
560 | | #define vcpu_has_lzcnt() (ctxt->cpuid->extd.abm) |
561 | | #define vcpu_has_sse4a() (ctxt->cpuid->extd.sse4a) |
562 | 7.17k | #define vcpu_has_misalignsse() (ctxt->cpuid->extd.misalignsse) |
563 | | #define vcpu_has_xop() (ctxt->cpuid->extd.xop) |
564 | | #define vcpu_has_fma4() (ctxt->cpuid->extd.fma4) |
565 | | #define vcpu_has_tbm() (ctxt->cpuid->extd.tbm) |
566 | | #define vcpu_has_clzero() (ctxt->cpuid->extd.clzero) |
567 | 53 | #define vcpu_has_wbnoinvd() (ctxt->cpuid->extd.wbnoinvd) |
568 | 1.38k | #define vcpu_has_nscb() (ctxt->cpuid->extd.nscb) |
569 | | #define vcpu_has_avx512_bmm() (ctxt->cpuid->extd.avx512_bmm) |
570 | | |
571 | | #define vcpu_has_bmi1() (ctxt->cpuid->feat.bmi1) |
572 | | #define vcpu_has_hle() (ctxt->cpuid->feat.hle) |
573 | | #define vcpu_has_avx2() (ctxt->cpuid->feat.avx2) |
574 | | #define vcpu_has_bmi2() (ctxt->cpuid->feat.bmi2) |
575 | | #define vcpu_has_invpcid() (ctxt->cpuid->feat.invpcid) |
576 | 639 | #define vcpu_has_rtm() (ctxt->cpuid->feat.rtm) |
577 | 0 | #define vcpu_has_mpx() (ctxt->cpuid->feat.mpx) |
578 | | #define vcpu_has_avx512f() (ctxt->cpuid->feat.avx512f) |
579 | | #define vcpu_has_avx512dq() (ctxt->cpuid->feat.avx512dq) |
580 | | #define vcpu_has_rdseed() (ctxt->cpuid->feat.rdseed) |
581 | | #define vcpu_has_adx() (ctxt->cpuid->feat.adx) |
582 | | #define vcpu_has_smap() (ctxt->cpuid->feat.smap) |
583 | | #define vcpu_has_avx512_ifma() (ctxt->cpuid->feat.avx512_ifma) |
584 | | #define vcpu_has_clflushopt() (ctxt->cpuid->feat.clflushopt) |
585 | | #define vcpu_has_clwb() (ctxt->cpuid->feat.clwb) |
586 | | #define vcpu_has_avx512cd() (ctxt->cpuid->feat.avx512cd) |
587 | | #define vcpu_has_sha() (ctxt->cpuid->feat.sha) |
588 | | #define vcpu_has_avx512bw() (ctxt->cpuid->feat.avx512bw) |
589 | | #define vcpu_has_avx512vl() (ctxt->cpuid->feat.avx512vl) |
590 | | #define vcpu_has_avx512_vbmi() (ctxt->cpuid->feat.avx512_vbmi) |
591 | | #define vcpu_has_avx512_vbmi2() (ctxt->cpuid->feat.avx512_vbmi2) |
592 | | #define vcpu_has_gfni() (ctxt->cpuid->feat.gfni) |
593 | | #define vcpu_has_vaes() (ctxt->cpuid->feat.vaes) |
594 | | #define vcpu_has_vpclmulqdq() (ctxt->cpuid->feat.vpclmulqdq) |
595 | | #define vcpu_has_avx512_vnni() (ctxt->cpuid->feat.avx512_vnni) |
596 | | #define vcpu_has_avx512_bitalg() (ctxt->cpuid->feat.avx512_bitalg) |
597 | | #define vcpu_has_avx512_vpopcntdq() (ctxt->cpuid->feat.avx512_vpopcntdq) |
598 | | #define vcpu_has_rdpid() (ctxt->cpuid->feat.rdpid) |
599 | | #define vcpu_has_movdiri() (ctxt->cpuid->feat.movdiri) |
600 | | #define vcpu_has_movdir64b() (ctxt->cpuid->feat.movdir64b) |
601 | | #define vcpu_has_enqcmd() (ctxt->cpuid->feat.enqcmd) |
602 | | #define vcpu_has_avx512_vp2intersect() (ctxt->cpuid->feat.avx512_vp2intersect) |
603 | | #define vcpu_has_serialize() (ctxt->cpuid->feat.serialize) |
604 | | #define vcpu_has_tsxldtrk() (ctxt->cpuid->feat.tsxldtrk) |
605 | | #define vcpu_has_avx512_fp16() (ctxt->cpuid->feat.avx512_fp16) |
606 | | #define vcpu_has_sha512() (ctxt->cpuid->feat.sha512) |
607 | | #define vcpu_has_sm3() (ctxt->cpuid->feat.sm3) |
608 | | #define vcpu_has_sm4() (ctxt->cpuid->feat.sm4) |
609 | | #define vcpu_has_avx_vnni() (ctxt->cpuid->feat.avx_vnni) |
610 | | #define vcpu_has_avx512_bf16() (ctxt->cpuid->feat.avx512_bf16) |
611 | | #define vcpu_has_cmpccxadd() (ctxt->cpuid->feat.cmpccxadd) |
612 | | #define vcpu_has_lkgs() (ctxt->cpuid->feat.lkgs) |
613 | | #define vcpu_has_wrmsrns() (ctxt->cpuid->feat.wrmsrns) |
614 | | #define vcpu_has_avx_ifma() (ctxt->cpuid->feat.avx_ifma) |
615 | | #define vcpu_has_avx_vnni_int8() (ctxt->cpuid->feat.avx_vnni_int8) |
616 | | #define vcpu_has_avx_ne_convert() (ctxt->cpuid->feat.avx_ne_convert) |
617 | | #define vcpu_has_avx_vnni_int16() (ctxt->cpuid->feat.avx_vnni_int16) |
618 | | |
619 | | #define vcpu_must_have(feat) \ |
620 | 190k | generate_exception_if(!vcpu_has_##feat(), X86_EXC_UD) |
621 | | |
622 | | #ifdef __XEN__ |
623 | | /* |
624 | | * Note the difference between vcpu_must_have(<feature>) and |
625 | | * host_and_vcpu_must_have(<feature>): The latter needs to be used when |
626 | | * emulation code is using the same instruction class for carrying out |
627 | | * the actual operation. |
628 | | */ |
629 | | # define host_and_vcpu_must_have(feat) ({ \ |
630 | | generate_exception_if(!cpu_has_##feat, X86_EXC_UD); \ |
631 | | vcpu_must_have(feat); \ |
632 | | }) |
633 | | #else |
634 | | /* |
635 | | * For the test harness both are fine to be used interchangeably, i.e. |
636 | | * features known to always be available (e.g. SSE/SSE2) to (64-bit) Xen |
637 | | * may be checked for by just vcpu_must_have(). |
638 | | */ |
639 | 124k | # define host_and_vcpu_must_have(feat) vcpu_must_have(feat) |
640 | | #endif |
641 | | |
642 | | /* |
643 | | * Instruction emulation: |
644 | | * Most instructions are emulated directly via a fragment of inline assembly |
645 | | * code. This allows us to save/restore EFLAGS and thus very easily pick up |
646 | | * any modified flags. |
647 | | */ |
648 | | |
649 | | #if defined(__x86_64__) |
650 | | #define _LO32 "k" /* force 32-bit operand */ |
651 | | #define _STK "%%rsp" /* stack pointer */ |
652 | | #elif defined(__i386__) |
653 | | #define _LO32 "" /* force 32-bit operand */ |
654 | | #define _STK "%%esp" /* stack pointer */ |
655 | | #endif |
656 | | |
657 | | /* Before executing instruction: restore necessary bits in EFLAGS. */ |
658 | | #define _PRE_EFLAGS(_sav, _msk, _tmp) \ |
659 | | /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); _sav &= ~_msk; */ \ |
660 | | "movl %"_LO32 _sav",%"_LO32 _tmp"; " \ |
661 | | "push %"_tmp"; " \ |
662 | | "push %"_tmp"; " \ |
663 | | "movl %"_msk",%"_LO32 _tmp"; " \ |
664 | | "andl %"_LO32 _tmp",("_STK"); " \ |
665 | | "pushf; " \ |
666 | | "notl %"_LO32 _tmp"; " \ |
667 | | "andl %"_LO32 _tmp",("_STK"); " \ |
668 | | "andl %"_LO32 _tmp", 2 * " STR(__SIZEOF_LONG__) "("_STK"); " \ |
669 | | "pop %"_tmp"; " \ |
670 | | "orl %"_LO32 _tmp",("_STK"); " \ |
671 | | "popf; " \ |
672 | | "pop %"_tmp"; " \ |
673 | | "movl %"_LO32 _tmp",%"_LO32 _sav"; " |
674 | | |
675 | | /* After executing instruction: write-back necessary bits in EFLAGS. */ |
676 | | #define _POST_EFLAGS(_sav, _msk, _tmp) \ |
677 | | /* _sav |= EFLAGS & _msk; */ \ |
678 | | "pushf; " \ |
679 | | "pop %"_tmp"; " \ |
680 | | "andl %"_msk",%"_LO32 _tmp"; " \ |
681 | | "orl %"_LO32 _tmp",%"_LO32 _sav"; " |
682 | | |
683 | | #ifdef __XEN__ |
684 | | |
685 | | # include <xen/domain_page.h> |
686 | | # include <asm/uaccess.h> |
687 | | |
688 | | # define get_stub(stb) ({ \ |
689 | | void *_ptr; \ |
690 | | BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX_INST_LEN + 1); \ |
691 | | ASSERT(!(stb).ptr); \ |
692 | | (stb).addr = this_cpu(stubs.addr) + STUB_BUF_SIZE / 2; \ |
693 | | (stb).ptr = map_domain_page(_mfn(this_cpu(stubs.mfn))) + \ |
694 | | ((stb).addr & ~PAGE_MASK); \ |
695 | | _ptr = memset((stb).ptr, 0xcc, STUB_BUF_SIZE / 2); \ |
696 | | if ( cpu_has_xen_ibt ) \ |
697 | | { \ |
698 | | place_endbr64(_ptr); \ |
699 | | _ptr += 4; \ |
700 | | } \ |
701 | | _ptr; \ |
702 | | }) |
703 | | |
704 | | # define put_stub(stb) ({ \ |
705 | | if ( (stb).ptr ) \ |
706 | | { \ |
707 | | unmap_domain_page((stb).ptr); \ |
708 | | (stb).ptr = NULL; \ |
709 | | } \ |
710 | | }) |
711 | | |
712 | | |
713 | | struct stub_exn { |
714 | | union stub_exception_token info; |
715 | | unsigned int line; |
716 | | }; |
717 | | |
718 | | # define invoke_stub(pre, post, constraints...) do { \ |
719 | | stub_exn.info = (union stub_exception_token) { .raw = ~0 }; \ |
720 | | stub_exn.line = __LINE__; /* Utility outweighs livepatching cost */ \ |
721 | | block_speculation(); /* SCSB */ \ |
722 | | asm volatile ( pre "\n\t" \ |
723 | | "INDIRECT_CALL %[stub]\n" \ |
724 | | ".Lret%=:\n\t" \ |
725 | | post "\n\t" \ |
726 | | ".Lskip%=:\n\t" \ |
727 | | ".pushsection .fixup,\"ax\"\n" \ |
728 | | ".Lfix%=:\n\t" \ |
729 | | "pop %[exn]\n\t" \ |
730 | | "jmp .Lskip%=\n\t" \ |
731 | | ".popsection\n\t" \ |
732 | | _ASM_EXTABLE(.Lret%=, .Lfix%=) \ |
733 | | : [exn] "+g" (stub_exn.info) ASM_CALL_CONSTRAINT, \ |
734 | | constraints, \ |
735 | | [stub] "r" (stub.func), \ |
736 | | "m" (*(uint8_t(*)[MAX_INST_LEN + 1])stub.ptr) ); \ |
737 | | if ( unlikely(~stub_exn.info.raw) ) \ |
738 | | goto emulation_stub_failure; \ |
739 | | } while (0) |
740 | | |
741 | | #else /* !__XEN__ */ |
742 | | |
743 | 146k | # define get_stub(stb) ({ \ |
744 | 146k | assert(!(stb).addr); \ |
745 | 146k | (void *)((stb).addr = (uintptr_t)(stb).buf); \ |
746 | 146k | }) |
747 | | |
748 | 667k | # define put_stub(stb) ((stb).addr = 0) |
749 | | |
750 | | struct stub_exn {}; |
751 | | |
752 | | # define invoke_stub(pre, post, constraints...) \ |
753 | 145k | asm volatile ( pre "\n\tcall *%[stub]\n\t" post \ |
754 | 145k | : constraints, [stub] "rm" (stub.func), \ |
755 | 145k | "m" (*(typeof(stub.buf) *)stub.addr) ) |
756 | | |
757 | | #endif /* __XEN__ */ |
758 | | |
759 | | int x86emul_get_cpl(struct x86_emulate_ctxt *ctxt, |
760 | | const struct x86_emulate_ops *ops); |
761 | | |
762 | | int x86emul_get_fpu(enum x86_emulate_fpu_type type, |
763 | | struct x86_emulate_ctxt *ctxt, |
764 | | const struct x86_emulate_ops *ops); |
765 | | |
766 | 144k | #define get_fpu(type) \ |
767 | 144k | do { \ |
768 | 144k | rc = x86emul_get_fpu(fpu_type = (type), ctxt, ops); \ |
769 | 144k | if ( rc ) goto done; \ |
770 | 144k | } while (0) |
771 | | |
772 | | int x86emul_decode(struct x86_emulate_state *s, |
773 | | struct x86_emulate_ctxt *ctxt, |
774 | | const struct x86_emulate_ops *ops); |
775 | | |
776 | | int x86emul_fpu(struct x86_emulate_state *s, |
777 | | struct cpu_user_regs *regs, |
778 | | struct operand *dst, |
779 | | struct operand *src, |
780 | | struct x86_emulate_ctxt *ctxt, |
781 | | const struct x86_emulate_ops *ops, |
782 | | unsigned int *insn_bytes, |
783 | | enum x86_emulate_fpu_type *fpu_type, |
784 | | mmval_t *mmvalp); |
785 | | int x86emul_0f01(struct x86_emulate_state *s, |
786 | | struct cpu_user_regs *regs, |
787 | | struct operand *dst, |
788 | | struct x86_emulate_ctxt *ctxt, |
789 | | const struct x86_emulate_ops *ops); |
790 | | int x86emul_0fae(struct x86_emulate_state *s, |
791 | | struct cpu_user_regs *regs, |
792 | | struct operand *dst, |
793 | | const struct operand *src, |
794 | | struct x86_emulate_ctxt *ctxt, |
795 | | const struct x86_emulate_ops *ops, |
796 | | enum x86_emulate_fpu_type *fpu_type); |
797 | | int x86emul_0fc7(struct x86_emulate_state *s, |
798 | | struct cpu_user_regs *regs, |
799 | | struct operand *dst, |
800 | | struct x86_emulate_ctxt *ctxt, |
801 | | const struct x86_emulate_ops *ops, |
802 | | mmval_t *mmvalp); |
803 | | |
804 | | /* Initialise output state in x86_emulate_ctxt */ |
805 | | static inline void init_context(struct x86_emulate_ctxt *ctxt) |
806 | 475k | { |
807 | 475k | ctxt->retire.raw = 0; |
808 | 475k | x86_emul_reset_event(ctxt); |
809 | 475k | } x86-emulate.c:init_context Line | Count | Source | 806 | 475k | { | 807 | 475k | ctxt->retire.raw = 0; | 808 | 475k | x86_emul_reset_event(ctxt); | 809 | 475k | } |
Unexecuted instantiation: 0f01.c:init_context Unexecuted instantiation: 0fae.c:init_context Unexecuted instantiation: 0fc7.c:init_context Unexecuted instantiation: decode.c:init_context Unexecuted instantiation: fpu.c:init_context |
810 | | |
811 | | static inline bool is_aligned(enum x86_segment seg, unsigned long offs, |
812 | | unsigned int size, struct x86_emulate_ctxt *ctxt, |
813 | | const struct x86_emulate_ops *ops) |
814 | 7.40k | { |
815 | 7.40k | struct segment_register reg; |
816 | | |
817 | | /* Expecting powers of two only. */ |
818 | 7.40k | ASSERT(!(size & (size - 1))); |
819 | | |
820 | 7.40k | if ( mode_64bit() && seg < x86_seg_fs ) |
821 | 945 | memset(®, 0, sizeof(reg)); |
822 | 6.45k | else |
823 | 6.45k | { |
824 | | /* No alignment checking when we have no way to read segment data. */ |
825 | 6.45k | if ( !ops->read_segment ) |
826 | 4.24k | return true; |
827 | | |
828 | 2.21k | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) |
829 | 0 | return false; |
830 | 2.21k | } |
831 | | |
832 | 3.15k | return !((reg.base + offs) & (size - 1)); |
833 | 7.40k | } Line | Count | Source | 814 | 7.17k | { | 815 | 7.17k | struct segment_register reg; | 816 | | | 817 | | /* Expecting powers of two only. */ | 818 | 7.17k | ASSERT(!(size & (size - 1))); | 819 | | | 820 | 7.17k | if ( mode_64bit() && seg < x86_seg_fs ) | 821 | 793 | memset(®, 0, sizeof(reg)); | 822 | 6.38k | else | 823 | 6.38k | { | 824 | | /* No alignment checking when we have no way to read segment data. */ | 825 | 6.38k | if ( !ops->read_segment ) | 826 | 4.19k | return true; | 827 | | | 828 | 2.18k | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 829 | 0 | return false; | 830 | 2.18k | } | 831 | | | 832 | 2.98k | return !((reg.base + offs) & (size - 1)); | 833 | 7.17k | } |
Unexecuted instantiation: 0f01.c:is_aligned Line | Count | Source | 814 | 5 | { | 815 | 5 | struct segment_register reg; | 816 | | | 817 | | /* Expecting powers of two only. */ | 818 | 5 | ASSERT(!(size & (size - 1))); | 819 | | | 820 | 5 | if ( mode_64bit() && seg < x86_seg_fs ) | 821 | 2 | memset(®, 0, sizeof(reg)); | 822 | 3 | else | 823 | 3 | { | 824 | | /* No alignment checking when we have no way to read segment data. */ | 825 | 3 | if ( !ops->read_segment ) | 826 | 1 | return true; | 827 | | | 828 | 2 | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 829 | 0 | return false; | 830 | 2 | } | 831 | | | 832 | 4 | return !((reg.base + offs) & (size - 1)); | 833 | 5 | } |
Line | Count | Source | 814 | 220 | { | 815 | 220 | struct segment_register reg; | 816 | | | 817 | | /* Expecting powers of two only. */ | 818 | 220 | ASSERT(!(size & (size - 1))); | 819 | | | 820 | 220 | if ( mode_64bit() && seg < x86_seg_fs ) | 821 | 150 | memset(®, 0, sizeof(reg)); | 822 | 70 | else | 823 | 70 | { | 824 | | /* No alignment checking when we have no way to read segment data. */ | 825 | 70 | if ( !ops->read_segment ) | 826 | 50 | return true; | 827 | | | 828 | 20 | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 829 | 0 | return false; | 830 | 20 | } | 831 | | | 832 | 170 | return !((reg.base + offs) & (size - 1)); | 833 | 220 | } |
Unexecuted instantiation: decode.c:is_aligned Unexecuted instantiation: fpu.c:is_aligned |
834 | | |
835 | | static inline bool umip_active(struct x86_emulate_ctxt *ctxt, |
836 | | const struct x86_emulate_ops *ops) |
837 | 13.7k | { |
838 | 13.7k | unsigned long cr4; |
839 | | |
840 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ |
841 | 13.7k | return x86emul_get_cpl(ctxt, ops) > 0 && |
842 | 4.48k | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && |
843 | 3.77k | (cr4 & X86_CR4_UMIP); |
844 | 13.7k | } x86-emulate.c:umip_active Line | Count | Source | 837 | 1.50k | { | 838 | 1.50k | unsigned long cr4; | 839 | | | 840 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ | 841 | 1.50k | return x86emul_get_cpl(ctxt, ops) > 0 && | 842 | 586 | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && | 843 | 343 | (cr4 & X86_CR4_UMIP); | 844 | 1.50k | } |
Line | Count | Source | 837 | 12.2k | { | 838 | 12.2k | unsigned long cr4; | 839 | | | 840 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ | 841 | 12.2k | return x86emul_get_cpl(ctxt, ops) > 0 && | 842 | 3.89k | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && | 843 | 3.43k | (cr4 & X86_CR4_UMIP); | 844 | 12.2k | } |
Unexecuted instantiation: 0fae.c:umip_active Unexecuted instantiation: 0fc7.c:umip_active Unexecuted instantiation: decode.c:umip_active Unexecuted instantiation: fpu.c:umip_active |
845 | | |
846 | | /* Compatibility function: read guest memory, zero-extend result to a ulong. */ |
847 | | static inline int read_ulong(enum x86_segment seg, |
848 | | unsigned long offset, |
849 | | unsigned long *val, |
850 | | unsigned int bytes, |
851 | | struct x86_emulate_ctxt *ctxt, |
852 | | const struct x86_emulate_ops *ops) |
853 | 124k | { |
854 | 124k | *val = 0; |
855 | 124k | return ops->read(seg, offset, val, bytes, ctxt); |
856 | 124k | } Line | Count | Source | 853 | 107k | { | 854 | 107k | *val = 0; | 855 | 107k | return ops->read(seg, offset, val, bytes, ctxt); | 856 | 107k | } |
Line | Count | Source | 853 | 16.9k | { | 854 | 16.9k | *val = 0; | 855 | 16.9k | return ops->read(seg, offset, val, bytes, ctxt); | 856 | 16.9k | } |
Unexecuted instantiation: 0fae.c:read_ulong Unexecuted instantiation: 0fc7.c:read_ulong Unexecuted instantiation: decode.c:read_ulong Unexecuted instantiation: fpu.c:read_ulong |
857 | | |
858 | | #endif /* X86_EMULATE_PRIVATE_H */ |