/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.36M | # define mode_64bit() (ctxt->addr_size == 64) |
43 | 401k | # define r(name) r ## name |
44 | 1.50M | # define PTR_POISON ((void *)0x8086000000008086UL) /* non-canonical */ |
45 | | #endif |
46 | | |
47 | | /* Operand sizes: 8-bit operands or specified/overridden size. */ |
48 | 460k | #define ByteOp (1<<0) /* 8-bit operands. */ |
49 | | /* Destination operand type. */ |
50 | 343k | #define DstNone (0<<1) /* No destination operand. */ |
51 | 2.25k | #define DstImplicit (0<<1) /* Destination operand is implicit in the opcode. */ |
52 | 3.59k | #define DstBitBase (1<<1) /* Memory operand, bit string. */ |
53 | 131k | #define DstReg (2<<1) /* Register operand. */ |
54 | 13.8k | #define DstEax DstReg /* Register EAX (aka DstReg with no ModRM) */ |
55 | 142k | #define DstMem (3<<1) /* Memory operand. */ |
56 | 538k | #define DstMask (3<<1) |
57 | | /* Source operand type. */ |
58 | 245k | #define SrcNone (0<<3) /* No source operand. */ |
59 | 1.20k | #define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */ |
60 | 53.8k | #define SrcReg (1<<3) /* Register operand. */ |
61 | | #define SrcEax SrcReg /* Register EAX (aka SrcReg with no ModRM) */ |
62 | 237k | #define SrcMem (2<<3) /* Memory operand. */ |
63 | 49.0k | #define SrcMem16 (3<<3) /* Memory operand (16-bit). */ |
64 | 47.2k | #define SrcImm (4<<3) /* Immediate operand. */ |
65 | 82.2k | #define SrcImmByte (5<<3) /* 8-bit sign-extended immediate operand. */ |
66 | 3.11k | #define SrcImm16 (6<<3) /* 16-bit zero-extended immediate operand. */ |
67 | 1.02M | #define SrcMask (7<<3) |
68 | | /* Generic ModRM decode. */ |
69 | 1.35M | #define ModRM (1<<6) |
70 | | /* vSIB addressing mode (0f38 extension opcodes only), aliasing ModRM. */ |
71 | 753 | #define vSIB (1<<6) |
72 | | /* Destination is only written; never read. */ |
73 | 152k | #define Mov (1<<7) |
74 | | /* VEX/EVEX (SIMD only): 2nd source operand unused (must be all ones) */ |
75 | 25.5k | #define TwoOp Mov |
76 | | /* All operands are implicit in the opcode. */ |
77 | 8 | #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 | 110k | #define REX_PREFIX 0x40 |
121 | 45.5k | #define REX_B 0x01 |
122 | 2.25k | #define REX_X 0x02 |
123 | 13.7k | #define REX_R 0x04 |
124 | 501k | #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 | | enum vex_opcx { |
199 | | vex_none, |
200 | | vex_0f, |
201 | | vex_0f38, |
202 | | vex_0f3a, |
203 | | evex_map5 = 5, |
204 | | evex_map6, |
205 | | }; |
206 | | |
207 | | enum vex_pfx { |
208 | | vex_np, |
209 | | vex_66, |
210 | | vex_f3, |
211 | | vex_f2 |
212 | | }; |
213 | | |
214 | 26.8k | #define VEX_PREFIX_DOUBLE_MASK 0x1 |
215 | 36.8k | #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 | 66.9k | #define imm1 ea.val |
333 | 2.95k | #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 | 108 | #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 | 124k | #define EFLAGS_MASK (X86_EFLAGS_OF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \ |
443 | 124k | 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 | 1.97k | #define EFLAGS_MODIFIABLE (X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_RF | \ |
450 | 1.97k | X86_EFLAGS_NT | X86_EFLAGS_IOPL | X86_EFLAGS_DF | \ |
451 | 1.97k | X86_EFLAGS_IF | X86_EFLAGS_TF | EFLAGS_MASK) |
452 | | |
453 | 357k | #define truncate_word(ea, byte_width) \ |
454 | 357k | ({ unsigned long __ea = (ea); \ |
455 | 357k | unsigned int _width = (byte_width); \ |
456 | 357k | ((_width == sizeof(unsigned long)) ? __ea : \ |
457 | 357k | (__ea & ((1UL << (_width << 3)) - 1))); \ |
458 | 357k | }) |
459 | 310k | #define truncate_ea(ea) truncate_word((ea), ad_bytes) |
460 | | |
461 | 746k | #define fail_if(p) \ |
462 | 746k | do { \ |
463 | 746k | rc = (p) ? X86EMUL_UNHANDLEABLE : X86EMUL_OKAY; \ |
464 | 746k | if ( rc ) goto done; \ |
465 | 746k | } while (0) |
466 | | |
467 | 224k | #define EXPECT(p) \ |
468 | 224k | do { \ |
469 | 224k | if ( unlikely(!(p)) ) \ |
470 | 224k | { \ |
471 | 0 | ASSERT_UNREACHABLE(); \ |
472 | 0 | goto unhandleable; \ |
473 | 0 | } \ |
474 | 224k | } while (0) |
475 | | |
476 | | static inline int mkec(uint8_t e, int32_t ec, ...) |
477 | 3.10k | { |
478 | 3.10k | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; |
479 | 3.10k | } Line | Count | Source | 477 | 2.93k | { | 478 | 2.93k | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 2.93k | } |
Line | Count | Source | 477 | 73 | { | 478 | 73 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 73 | } |
Line | Count | Source | 477 | 23 | { | 478 | 23 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 23 | } |
Line | Count | Source | 477 | 9 | { | 478 | 9 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 9 | } |
Line | Count | Source | 477 | 48 | { | 478 | 48 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 48 | } |
Line | Count | Source | 477 | 12 | { | 478 | 12 | return (e < 32 && ((1u << e) & X86_EXC_HAVE_EC)) ? ec : X86_EVENT_NO_EC; | 479 | 12 | } |
|
480 | | |
481 | 3.99M | #define generate_exception_if(p, e, ec...) \ |
482 | 6.11M | ({ if ( (p) ) { \ |
483 | 3.10k | x86_emul_hw_exception(e, mkec(e, ##ec, 0), ctxt); \ |
484 | 3.10k | rc = X86EMUL_EXCEPTION; \ |
485 | 3.10k | goto done; \ |
486 | 3.10k | } \ |
487 | 349k | }) |
488 | | |
489 | 191 | #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 | 41.7k | { |
496 | 41.7k | unsigned long cr0; |
497 | 41.7k | int rc; |
498 | | |
499 | 41.7k | if ( ops->read_cr == NULL ) |
500 | 2.73k | return 0; |
501 | | |
502 | 38.9k | rc = ops->read_cr(0, &cr0, ctxt); |
503 | 38.9k | return (!rc && !(cr0 & X86_CR0_PE)); |
504 | 41.7k | } x86-emulate.c:in_realmode Line | Count | Source | 495 | 13.9k | { | 496 | 13.9k | unsigned long cr0; | 497 | 13.9k | int rc; | 498 | | | 499 | 13.9k | if ( ops->read_cr == NULL ) | 500 | 2.16k | return 0; | 501 | | | 502 | 11.8k | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 11.8k | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 13.9k | } |
Line | Count | Source | 495 | 441 | { | 496 | 441 | unsigned long cr0; | 497 | 441 | int rc; | 498 | | | 499 | 441 | if ( ops->read_cr == NULL ) | 500 | 33 | return 0; | 501 | | | 502 | 408 | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 408 | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 441 | } |
Unexecuted instantiation: 0fae.c:in_realmode Unexecuted instantiation: 0fc7.c:in_realmode Line | Count | Source | 495 | 27.2k | { | 496 | 27.2k | unsigned long cr0; | 497 | 27.2k | int rc; | 498 | | | 499 | 27.2k | if ( ops->read_cr == NULL ) | 500 | 538 | return 0; | 501 | | | 502 | 26.7k | rc = ops->read_cr(0, &cr0, ctxt); | 503 | 26.7k | return (!rc && !(cr0 & X86_CR0_PE)); | 504 | 27.2k | } |
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 | 13.9k | { |
511 | 13.9k | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); |
512 | 13.9k | } x86-emulate.c:in_protmode Line | Count | Source | 510 | 13.5k | { | 511 | 13.5k | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); | 512 | 13.5k | } |
Line | Count | Source | 510 | 441 | { | 511 | 441 | return !(in_realmode(ctxt, ops) || (ctxt->regs->eflags & X86_EFLAGS_VM)); | 512 | 441 | } |
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 | 3.77k | #define mode_ring0() ({ \ |
515 | 3.77k | int _cpl = x86emul_get_cpl(ctxt, ops); \ |
516 | 3.77k | fail_if(_cpl < 0); \ |
517 | 3.77k | (_cpl == 0); \ |
518 | 2.80k | }) |
519 | | |
520 | | static inline bool |
521 | | _amd_like(const struct cpu_policy *cp) |
522 | 19.4k | { |
523 | 19.4k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); |
524 | 19.4k | } Line | Count | Source | 522 | 15.5k | { | 523 | 15.5k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); | 524 | 15.5k | } |
Unexecuted instantiation: 0f01.c:_amd_like Unexecuted instantiation: 0fae.c:_amd_like Unexecuted instantiation: 0fc7.c:_amd_like Line | Count | Source | 522 | 3.93k | { | 523 | 3.93k | return cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON); | 524 | 3.93k | } |
Unexecuted instantiation: fpu.c:_amd_like |
525 | | |
526 | | static inline bool |
527 | | amd_like(const struct x86_emulate_ctxt *ctxt) |
528 | 15.1k | { |
529 | 15.1k | return _amd_like(ctxt->cpu_policy); |
530 | 15.1k | } Line | Count | Source | 528 | 11.2k | { | 529 | 11.2k | return _amd_like(ctxt->cpu_policy); | 530 | 11.2k | } |
Unexecuted instantiation: 0f01.c:amd_like Unexecuted instantiation: 0fae.c:amd_like Unexecuted instantiation: 0fc7.c:amd_like Line | Count | Source | 528 | 3.93k | { | 529 | 3.93k | return _amd_like(ctxt->cpu_policy); | 530 | 3.93k | } |
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 | 487 | #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 | 8.14k | #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 | 218 | #define vcpu_has_wbnoinvd() (ctxt->cpuid->extd.wbnoinvd) |
568 | 2.97k | #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 | 22 | #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_movrs() (ctxt->cpuid->feat.movrs) |
616 | | #define vcpu_has_avx_vnni_int8() (ctxt->cpuid->feat.avx_vnni_int8) |
617 | | #define vcpu_has_avx_ne_convert() (ctxt->cpuid->feat.avx_ne_convert) |
618 | | #define vcpu_has_avx_vnni_int16() (ctxt->cpuid->feat.avx_vnni_int16) |
619 | | |
620 | | #define vcpu_must_have(feat) \ |
621 | 229k | generate_exception_if(!vcpu_has_##feat(), X86_EXC_UD) |
622 | | |
623 | | /* |
624 | | * Instruction emulation: |
625 | | * Most instructions are emulated directly via a fragment of inline assembly |
626 | | * code. This allows us to save/restore EFLAGS and thus very easily pick up |
627 | | * any modified flags. |
628 | | */ |
629 | | |
630 | | #if defined(__x86_64__) |
631 | | #define _LO32 "k" /* force 32-bit operand */ |
632 | | #define _STK "%%rsp" /* stack pointer */ |
633 | | #elif defined(__i386__) |
634 | | #define _LO32 "" /* force 32-bit operand */ |
635 | | #define _STK "%%esp" /* stack pointer */ |
636 | | #endif |
637 | | |
638 | | /* Before executing instruction: restore necessary bits in EFLAGS. */ |
639 | | #define _PRE_EFLAGS(_sav, _msk, _tmp) \ |
640 | | /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); _sav &= ~_msk; */ \ |
641 | | "movl %"_LO32 _sav",%"_LO32 _tmp"; " \ |
642 | | "push %"_tmp"; " \ |
643 | | "push %"_tmp"; " \ |
644 | | "movl %"_msk",%"_LO32 _tmp"; " \ |
645 | | "andl %"_LO32 _tmp",("_STK"); " \ |
646 | | "pushf; " \ |
647 | | "notl %"_LO32 _tmp"; " \ |
648 | | "andl %"_LO32 _tmp",("_STK"); " \ |
649 | | "andl %"_LO32 _tmp", 2 * " STR(__SIZEOF_LONG__) "("_STK"); " \ |
650 | | "pop %"_tmp"; " \ |
651 | | "orl %"_LO32 _tmp",("_STK"); " \ |
652 | | "popf; " \ |
653 | | "pop %"_tmp"; " \ |
654 | | "movl %"_LO32 _tmp",%"_LO32 _sav"; " |
655 | | |
656 | | /* After executing instruction: write-back necessary bits in EFLAGS. */ |
657 | | #define _POST_EFLAGS(_sav, _msk, _tmp) \ |
658 | | /* _sav |= EFLAGS & _msk; */ \ |
659 | | "pushf; " \ |
660 | | "pop %"_tmp"; " \ |
661 | | "andl %"_msk",%"_LO32 _tmp"; " \ |
662 | | "orl %"_LO32 _tmp",%"_LO32 _sav"; " |
663 | | |
664 | | #ifdef __XEN__ |
665 | | |
666 | | # include <xen/domain_page.h> |
667 | | # include <asm/uaccess.h> |
668 | | |
669 | | # define get_stub(stb) ({ \ |
670 | | void *_ptr; \ |
671 | | BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX_INST_LEN + 1); \ |
672 | | ASSERT(!(stb).ptr); \ |
673 | | (stb).addr = this_cpu(stubs.addr) + STUB_BUF_SIZE / 2; \ |
674 | | (stb).ptr = map_domain_page(_mfn(this_cpu(stubs.mfn))) + \ |
675 | | ((stb).addr & ~PAGE_MASK); \ |
676 | | _ptr = memset((stb).ptr, 0xcc, STUB_BUF_SIZE / 2); \ |
677 | | if ( cpu_has_xen_ibt ) \ |
678 | | { \ |
679 | | place_endbr64(_ptr); \ |
680 | | _ptr += 4; \ |
681 | | } \ |
682 | | _ptr; \ |
683 | | }) |
684 | | |
685 | | # define put_stub(stb) ({ \ |
686 | | if ( (stb).ptr ) \ |
687 | | { \ |
688 | | unmap_domain_page((stb).ptr); \ |
689 | | (stb).ptr = NULL; \ |
690 | | } \ |
691 | | }) |
692 | | |
693 | | |
694 | | struct stub_exn { |
695 | | union stub_exception_token info; |
696 | | unsigned int line; |
697 | | }; |
698 | | |
699 | | # define invoke_stub(pre, post, constraints...) do { \ |
700 | | stub_exn.info = (union stub_exception_token) { .raw = ~0 }; \ |
701 | | stub_exn.line = __LINE__; /* Utility outweighs livepatching cost */ \ |
702 | | block_speculation(); /* SCSB */ \ |
703 | | asm volatile ( pre "\n\t" \ |
704 | | "INDIRECT_CALL %[stub]\n" \ |
705 | | ".Lret%=:\n\t" \ |
706 | | post "\n\t" \ |
707 | | ".Lskip%=:\n\t" \ |
708 | | ".pushsection .fixup,\"ax\"\n" \ |
709 | | ".Lfix%=:\n\t" \ |
710 | | "pop %[exn]\n\t" \ |
711 | | "jmp .Lskip%=\n\t" \ |
712 | | ".popsection\n\t" \ |
713 | | _ASM_EXTABLE(.Lret%=, .Lfix%=) \ |
714 | | : [exn] "+g" (stub_exn.info) ASM_CALL_CONSTRAINT, \ |
715 | | constraints, \ |
716 | | [stub] "r" (stub.func), \ |
717 | | "m" (*(uint8_t(*)[MAX_INST_LEN + 1])stub.ptr) ); \ |
718 | | if ( unlikely(~stub_exn.info.raw) ) \ |
719 | | goto emulation_stub_failure; \ |
720 | | } while (0) |
721 | | |
722 | | #else /* !__XEN__ */ |
723 | | |
724 | 182k | # define get_stub(stb) ({ \ |
725 | 182k | assert(!(stb).addr); \ |
726 | 182k | (void *)((stb).addr = (uintptr_t)(stb).buf); \ |
727 | 182k | }) |
728 | | |
729 | 742k | # define put_stub(stb) ((stb).addr = 0) |
730 | | |
731 | | struct stub_exn {}; |
732 | | |
733 | | # define invoke_stub(pre, post, constraints...) \ |
734 | 181k | asm volatile ( pre "\n\tcall *%[stub]\n\t" post \ |
735 | 181k | : constraints, [stub] "rm" (stub.func), \ |
736 | 181k | "m" (*(typeof(stub.buf) *)stub.addr) ) |
737 | | |
738 | | #endif /* __XEN__ */ |
739 | | |
740 | | int x86emul_get_cpl(struct x86_emulate_ctxt *ctxt, |
741 | | const struct x86_emulate_ops *ops); |
742 | | |
743 | | int x86emul_get_fpu(enum x86_emulate_fpu_type type, |
744 | | struct x86_emulate_ctxt *ctxt, |
745 | | const struct x86_emulate_ops *ops); |
746 | | |
747 | 179k | #define get_fpu(type) \ |
748 | 179k | do { \ |
749 | 179k | rc = x86emul_get_fpu(fpu_type = (type), ctxt, ops); \ |
750 | 179k | if ( rc ) goto done; \ |
751 | 179k | } while (0) |
752 | | |
753 | | int x86emul_decode(struct x86_emulate_state *s, |
754 | | struct x86_emulate_ctxt *ctxt, |
755 | | const struct x86_emulate_ops *ops); |
756 | | |
757 | | int x86emul_fpu(struct x86_emulate_state *s, |
758 | | struct cpu_user_regs *regs, |
759 | | struct operand *dst, |
760 | | struct operand *src, |
761 | | struct x86_emulate_ctxt *ctxt, |
762 | | const struct x86_emulate_ops *ops, |
763 | | unsigned int *insn_bytes, |
764 | | enum x86_emulate_fpu_type *fpu_type, |
765 | | mmval_t *mmvalp); |
766 | | int x86emul_0f01(struct x86_emulate_state *s, |
767 | | struct cpu_user_regs *regs, |
768 | | struct operand *dst, |
769 | | struct x86_emulate_ctxt *ctxt, |
770 | | const struct x86_emulate_ops *ops); |
771 | | int x86emul_0fae(struct x86_emulate_state *s, |
772 | | struct cpu_user_regs *regs, |
773 | | struct operand *dst, |
774 | | const struct operand *src, |
775 | | struct x86_emulate_ctxt *ctxt, |
776 | | const struct x86_emulate_ops *ops, |
777 | | enum x86_emulate_fpu_type *fpu_type); |
778 | | int x86emul_0fc7(struct x86_emulate_state *s, |
779 | | struct cpu_user_regs *regs, |
780 | | struct operand *dst, |
781 | | struct x86_emulate_ctxt *ctxt, |
782 | | const struct x86_emulate_ops *ops, |
783 | | mmval_t *mmvalp); |
784 | | |
785 | | /* Initialise output state in x86_emulate_ctxt */ |
786 | | static inline void init_context(struct x86_emulate_ctxt *ctxt) |
787 | 502k | { |
788 | 502k | ctxt->retire.raw = 0; |
789 | 502k | x86_emul_reset_event(ctxt); |
790 | 502k | } x86-emulate.c:init_context Line | Count | Source | 787 | 502k | { | 788 | 502k | ctxt->retire.raw = 0; | 789 | 502k | x86_emul_reset_event(ctxt); | 790 | 502k | } |
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 |
791 | | |
792 | | static inline bool is_aligned(enum x86_segment seg, unsigned long offs, |
793 | | unsigned int size, struct x86_emulate_ctxt *ctxt, |
794 | | const struct x86_emulate_ops *ops) |
795 | 8.50k | { |
796 | 8.50k | struct segment_register reg; |
797 | | |
798 | | /* Expecting powers of two only. */ |
799 | 8.50k | ASSERT(!(size & (size - 1))); |
800 | | |
801 | 8.50k | if ( mode_64bit() && seg < x86_seg_fs ) |
802 | 1.28k | memset(®, 0, sizeof(reg)); |
803 | 7.22k | else |
804 | 7.22k | { |
805 | | /* No alignment checking when we have no way to read segment data. */ |
806 | 7.22k | if ( !ops->read_segment ) |
807 | 3.76k | return true; |
808 | | |
809 | 3.45k | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) |
810 | 0 | return false; |
811 | 3.45k | } |
812 | | |
813 | 4.73k | return !((reg.base + offs) & (size - 1)); |
814 | 8.50k | } Line | Count | Source | 795 | 8.14k | { | 796 | 8.14k | struct segment_register reg; | 797 | | | 798 | | /* Expecting powers of two only. */ | 799 | 8.14k | ASSERT(!(size & (size - 1))); | 800 | | | 801 | 8.14k | if ( mode_64bit() && seg < x86_seg_fs ) | 802 | 1.10k | memset(®, 0, sizeof(reg)); | 803 | 7.03k | else | 804 | 7.03k | { | 805 | | /* No alignment checking when we have no way to read segment data. */ | 806 | 7.03k | if ( !ops->read_segment ) | 807 | 3.68k | return true; | 808 | | | 809 | 3.35k | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 810 | 0 | return false; | 811 | 3.35k | } | 812 | | | 813 | 4.45k | return !((reg.base + offs) & (size - 1)); | 814 | 8.14k | } |
Unexecuted instantiation: 0f01.c:is_aligned Line | Count | Source | 795 | 4 | { | 796 | 4 | struct segment_register reg; | 797 | | | 798 | | /* Expecting powers of two only. */ | 799 | 4 | ASSERT(!(size & (size - 1))); | 800 | | | 801 | 4 | if ( mode_64bit() && seg < x86_seg_fs ) | 802 | 1 | memset(®, 0, sizeof(reg)); | 803 | 3 | else | 804 | 3 | { | 805 | | /* No alignment checking when we have no way to read segment data. */ | 806 | 3 | if ( !ops->read_segment ) | 807 | 1 | return true; | 808 | | | 809 | 2 | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 810 | 0 | return false; | 811 | 2 | } | 812 | | | 813 | 3 | return !((reg.base + offs) & (size - 1)); | 814 | 4 | } |
Line | Count | Source | 795 | 356 | { | 796 | 356 | struct segment_register reg; | 797 | | | 798 | | /* Expecting powers of two only. */ | 799 | 356 | ASSERT(!(size & (size - 1))); | 800 | | | 801 | 356 | if ( mode_64bit() && seg < x86_seg_fs ) | 802 | 175 | memset(®, 0, sizeof(reg)); | 803 | 181 | else | 804 | 181 | { | 805 | | /* No alignment checking when we have no way to read segment data. */ | 806 | 181 | if ( !ops->read_segment ) | 807 | 79 | return true; | 808 | | | 809 | 102 | if ( ops->read_segment(seg, ®, ctxt) != X86EMUL_OKAY ) | 810 | 0 | return false; | 811 | 102 | } | 812 | | | 813 | 277 | return !((reg.base + offs) & (size - 1)); | 814 | 356 | } |
Unexecuted instantiation: decode.c:is_aligned Unexecuted instantiation: fpu.c:is_aligned |
815 | | |
816 | | static inline bool umip_active(struct x86_emulate_ctxt *ctxt, |
817 | | const struct x86_emulate_ops *ops) |
818 | 15.1k | { |
819 | 15.1k | unsigned long cr4; |
820 | | |
821 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ |
822 | 15.1k | return x86emul_get_cpl(ctxt, ops) > 0 && |
823 | 5.76k | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && |
824 | 5.03k | (cr4 & X86_CR4_UMIP); |
825 | 15.1k | } x86-emulate.c:umip_active Line | Count | Source | 818 | 949 | { | 819 | 949 | unsigned long cr4; | 820 | | | 821 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ | 822 | 949 | return x86emul_get_cpl(ctxt, ops) > 0 && | 823 | 413 | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && | 824 | 249 | (cr4 & X86_CR4_UMIP); | 825 | 949 | } |
Line | Count | Source | 818 | 14.2k | { | 819 | 14.2k | unsigned long cr4; | 820 | | | 821 | | /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ | 822 | 14.2k | return x86emul_get_cpl(ctxt, ops) > 0 && | 823 | 5.35k | ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && | 824 | 4.78k | (cr4 & X86_CR4_UMIP); | 825 | 14.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 |
826 | | |
827 | | /* Compatibility function: read guest memory, zero-extend result to a ulong. */ |
828 | | static inline int read_ulong(enum x86_segment seg, |
829 | | unsigned long offset, |
830 | | unsigned long *val, |
831 | | unsigned int bytes, |
832 | | struct x86_emulate_ctxt *ctxt, |
833 | | const struct x86_emulate_ops *ops) |
834 | 112k | { |
835 | 112k | *val = 0; |
836 | 112k | return ops->read(seg, offset, val, bytes, ctxt); |
837 | 112k | } Line | Count | Source | 834 | 93.0k | { | 835 | 93.0k | *val = 0; | 836 | 93.0k | return ops->read(seg, offset, val, bytes, ctxt); | 837 | 93.0k | } |
Line | Count | Source | 834 | 19.5k | { | 835 | 19.5k | *val = 0; | 836 | 19.5k | return ops->read(seg, offset, val, bytes, ctxt); | 837 | 19.5k | } |
Unexecuted instantiation: 0fae.c:read_ulong Unexecuted instantiation: 0fc7.c:read_ulong Unexecuted instantiation: decode.c:read_ulong Unexecuted instantiation: fpu.c:read_ulong |
838 | | |
839 | | #endif /* X86_EMULATE_PRIVATE_H */ |