.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /****************************************************************************** |
---|
2 | 3 | * emulate.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
14 | 15 | * Avi Kivity <avi@qumranet.com> |
---|
15 | 16 | * Yaniv Kamay <yaniv@qumranet.com> |
---|
16 | 17 | * |
---|
17 | | - * This work is licensed under the terms of the GNU GPL, version 2. See |
---|
18 | | - * the COPYING file in the top-level directory. |
---|
19 | | - * |
---|
20 | 18 | * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 |
---|
21 | 19 | */ |
---|
22 | 20 | |
---|
23 | 21 | #include <linux/kvm_host.h> |
---|
24 | 22 | #include "kvm_cache_regs.h" |
---|
25 | | -#include <asm/kvm_emulate.h> |
---|
| 23 | +#include "kvm_emulate.h" |
---|
26 | 24 | #include <linux/stringify.h> |
---|
| 25 | +#include <asm/fpu/api.h> |
---|
27 | 26 | #include <asm/debugreg.h> |
---|
28 | 27 | #include <asm/nospec-branch.h> |
---|
29 | 28 | |
---|
.. | .. |
---|
189 | 188 | #define X8(x...) X4(x), X4(x) |
---|
190 | 189 | #define X16(x...) X8(x), X8(x) |
---|
191 | 190 | |
---|
192 | | -#define NR_FASTOP (ilog2(sizeof(ulong)) + 1) |
---|
193 | | -#define FASTOP_SIZE 8 |
---|
194 | | - |
---|
195 | | -/* |
---|
196 | | - * fastop functions have a special calling convention: |
---|
197 | | - * |
---|
198 | | - * dst: rax (in/out) |
---|
199 | | - * src: rdx (in/out) |
---|
200 | | - * src2: rcx (in) |
---|
201 | | - * flags: rflags (in/out) |
---|
202 | | - * ex: rsi (in:fastop pointer, out:zero if exception) |
---|
203 | | - * |
---|
204 | | - * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for |
---|
205 | | - * different operand sizes can be reached by calculation, rather than a jump |
---|
206 | | - * table (which would be bigger than the code). |
---|
207 | | - * |
---|
208 | | - * fastop functions are declared as taking a never-defined fastop parameter, |
---|
209 | | - * so they can't be called from C directly. |
---|
210 | | - */ |
---|
211 | | - |
---|
212 | | -struct fastop; |
---|
213 | | - |
---|
214 | 191 | struct opcode { |
---|
215 | 192 | u64 flags : 56; |
---|
216 | 193 | u64 intercept : 8; |
---|
.. | .. |
---|
312 | 289 | #define ON64(x) |
---|
313 | 290 | #endif |
---|
314 | 291 | |
---|
315 | | -static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); |
---|
| 292 | +/* |
---|
| 293 | + * fastop functions have a special calling convention: |
---|
| 294 | + * |
---|
| 295 | + * dst: rax (in/out) |
---|
| 296 | + * src: rdx (in/out) |
---|
| 297 | + * src2: rcx (in) |
---|
| 298 | + * flags: rflags (in/out) |
---|
| 299 | + * ex: rsi (in:fastop pointer, out:zero if exception) |
---|
| 300 | + * |
---|
| 301 | + * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for |
---|
| 302 | + * different operand sizes can be reached by calculation, rather than a jump |
---|
| 303 | + * table (which would be bigger than the code). |
---|
| 304 | + * |
---|
| 305 | + * The 16 byte alignment, considering 5 bytes for the RET thunk, 3 for ENDBR |
---|
| 306 | + * and 1 for the straight line speculation INT3, leaves 7 bytes for the |
---|
| 307 | + * body of the function. Currently none is larger than 4. |
---|
| 308 | + */ |
---|
| 309 | +static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); |
---|
316 | 310 | |
---|
317 | | -#define FOP_FUNC(name) \ |
---|
| 311 | +#define FASTOP_SIZE 16 |
---|
| 312 | + |
---|
| 313 | +#define __FOP_FUNC(name) \ |
---|
318 | 314 | ".align " __stringify(FASTOP_SIZE) " \n\t" \ |
---|
319 | 315 | ".type " name ", @function \n\t" \ |
---|
320 | 316 | name ":\n\t" |
---|
321 | 317 | |
---|
322 | | -#define FOP_RET "ret \n\t" |
---|
| 318 | +#define FOP_FUNC(name) \ |
---|
| 319 | + __FOP_FUNC(#name) |
---|
323 | 320 | |
---|
324 | | -#define FOP_START(op) \ |
---|
| 321 | +#define __FOP_RET(name) \ |
---|
| 322 | + ASM_RET \ |
---|
| 323 | + ".size " name ", .-" name "\n\t" |
---|
| 324 | + |
---|
| 325 | +#define FOP_RET(name) \ |
---|
| 326 | + __FOP_RET(#name) |
---|
| 327 | + |
---|
| 328 | +#define __FOP_START(op, align) \ |
---|
325 | 329 | extern void em_##op(struct fastop *fake); \ |
---|
326 | 330 | asm(".pushsection .text, \"ax\" \n\t" \ |
---|
327 | 331 | ".global em_" #op " \n\t" \ |
---|
328 | | - FOP_FUNC("em_" #op) |
---|
| 332 | + ".align " __stringify(align) " \n\t" \ |
---|
| 333 | + "em_" #op ":\n\t" |
---|
| 334 | + |
---|
| 335 | +#define FOP_START(op) __FOP_START(op, FASTOP_SIZE) |
---|
329 | 336 | |
---|
330 | 337 | #define FOP_END \ |
---|
331 | 338 | ".popsection") |
---|
332 | 339 | |
---|
| 340 | +#define __FOPNOP(name) \ |
---|
| 341 | + __FOP_FUNC(name) \ |
---|
| 342 | + __FOP_RET(name) |
---|
| 343 | + |
---|
333 | 344 | #define FOPNOP() \ |
---|
334 | | - FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \ |
---|
335 | | - FOP_RET |
---|
| 345 | + __FOPNOP(__stringify(__UNIQUE_ID(nop))) |
---|
336 | 346 | |
---|
337 | 347 | #define FOP1E(op, dst) \ |
---|
338 | | - FOP_FUNC(#op "_" #dst) \ |
---|
339 | | - "10: " #op " %" #dst " \n\t" FOP_RET |
---|
| 348 | + __FOP_FUNC(#op "_" #dst) \ |
---|
| 349 | + "10: " #op " %" #dst " \n\t" \ |
---|
| 350 | + __FOP_RET(#op "_" #dst) |
---|
340 | 351 | |
---|
341 | 352 | #define FOP1EEX(op, dst) \ |
---|
342 | 353 | FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception) |
---|
.. | .. |
---|
368 | 379 | FOP_END |
---|
369 | 380 | |
---|
370 | 381 | #define FOP2E(op, dst, src) \ |
---|
371 | | - FOP_FUNC(#op "_" #dst "_" #src) \ |
---|
372 | | - #op " %" #src ", %" #dst " \n\t" FOP_RET |
---|
| 382 | + __FOP_FUNC(#op "_" #dst "_" #src) \ |
---|
| 383 | + #op " %" #src ", %" #dst " \n\t" \ |
---|
| 384 | + __FOP_RET(#op "_" #dst "_" #src) |
---|
373 | 385 | |
---|
374 | 386 | #define FASTOP2(op) \ |
---|
375 | 387 | FOP_START(op) \ |
---|
.. | .. |
---|
407 | 419 | FOP_END |
---|
408 | 420 | |
---|
409 | 421 | #define FOP3E(op, dst, src, src2) \ |
---|
410 | | - FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \ |
---|
411 | | - #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET |
---|
| 422 | + __FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \ |
---|
| 423 | + #op " %" #src2 ", %" #src ", %" #dst " \n\t"\ |
---|
| 424 | + __FOP_RET(#op "_" #dst "_" #src "_" #src2) |
---|
412 | 425 | |
---|
413 | 426 | /* 3-operand, word-only, src2=cl */ |
---|
414 | 427 | #define FASTOP3WCL(op) \ |
---|
.. | .. |
---|
420 | 433 | FOP_END |
---|
421 | 434 | |
---|
422 | 435 | /* Special case for SETcc - 1 instruction per cc */ |
---|
| 436 | + |
---|
| 437 | +/* |
---|
| 438 | + * Depending on .config the SETcc functions look like: |
---|
| 439 | + * |
---|
| 440 | + * SETcc %al [3 bytes] |
---|
| 441 | + * RET | JMP __x86_return_thunk [1,5 bytes; CONFIG_RETHUNK] |
---|
| 442 | + * INT3 [1 byte; CONFIG_SLS] |
---|
| 443 | + */ |
---|
| 444 | +#define SETCC_ALIGN 16 |
---|
| 445 | + |
---|
423 | 446 | #define FOP_SETCC(op) \ |
---|
424 | | - ".align 4 \n\t" \ |
---|
| 447 | + ".align " __stringify(SETCC_ALIGN) " \n\t" \ |
---|
425 | 448 | ".type " #op ", @function \n\t" \ |
---|
426 | 449 | #op ": \n\t" \ |
---|
427 | 450 | #op " %al \n\t" \ |
---|
428 | | - FOP_RET |
---|
| 451 | + __FOP_RET(#op) \ |
---|
| 452 | + ".skip " __stringify(SETCC_ALIGN) " - (.-" #op "), 0xcc \n\t" |
---|
429 | 453 | |
---|
430 | 454 | asm(".pushsection .fixup, \"ax\"\n" |
---|
431 | | - ".global kvm_fastop_exception \n" |
---|
432 | | - "kvm_fastop_exception: xor %esi, %esi; ret\n" |
---|
| 455 | + "kvm_fastop_exception: xor %esi, %esi; " ASM_RET |
---|
433 | 456 | ".popsection"); |
---|
434 | 457 | |
---|
435 | | -FOP_START(setcc) |
---|
| 458 | +__FOP_START(setcc, SETCC_ALIGN) |
---|
436 | 459 | FOP_SETCC(seto) |
---|
437 | 460 | FOP_SETCC(setno) |
---|
438 | 461 | FOP_SETCC(setc) |
---|
.. | .. |
---|
451 | 474 | FOP_SETCC(setnle) |
---|
452 | 475 | FOP_END; |
---|
453 | 476 | |
---|
454 | | -FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET |
---|
| 477 | +FOP_START(salc) |
---|
| 478 | +FOP_FUNC(salc) |
---|
| 479 | +"pushf; sbb %al, %al; popf \n\t" |
---|
| 480 | +FOP_RET(salc) |
---|
455 | 481 | FOP_END; |
---|
456 | 482 | |
---|
457 | 483 | /* |
---|
.. | .. |
---|
654 | 680 | ctxt->ops->set_segment(ctxt, selector, &desc, base3, seg); |
---|
655 | 681 | } |
---|
656 | 682 | |
---|
| 683 | +static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt) |
---|
| 684 | +{ |
---|
| 685 | + return (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_LA57) ? 57 : 48; |
---|
| 686 | +} |
---|
| 687 | + |
---|
| 688 | +static inline bool emul_is_noncanonical_address(u64 la, |
---|
| 689 | + struct x86_emulate_ctxt *ctxt) |
---|
| 690 | +{ |
---|
| 691 | + return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la; |
---|
| 692 | +} |
---|
| 693 | + |
---|
657 | 694 | /* |
---|
658 | 695 | * x86 defines three classes of vector instructions: explicitly |
---|
659 | 696 | * aligned, explicitly unaligned, and the rest, which change behaviour |
---|
.. | .. |
---|
759 | 796 | ctxt->mode, linear); |
---|
760 | 797 | } |
---|
761 | 798 | |
---|
762 | | -static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst, |
---|
763 | | - enum x86emul_mode mode) |
---|
| 799 | +static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst) |
---|
764 | 800 | { |
---|
765 | 801 | ulong linear; |
---|
766 | 802 | int rc; |
---|
.. | .. |
---|
770 | 806 | |
---|
771 | 807 | if (ctxt->op_bytes != sizeof(unsigned long)) |
---|
772 | 808 | addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1); |
---|
773 | | - rc = __linearize(ctxt, addr, &max_size, 1, false, true, mode, &linear); |
---|
| 809 | + rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear); |
---|
774 | 810 | if (rc == X86EMUL_CONTINUE) |
---|
775 | 811 | ctxt->_eip = addr.ea; |
---|
776 | 812 | return rc; |
---|
777 | 813 | } |
---|
778 | 814 | |
---|
779 | | -static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) |
---|
| 815 | +static inline int emulator_recalc_and_set_mode(struct x86_emulate_ctxt *ctxt) |
---|
780 | 816 | { |
---|
781 | | - return assign_eip(ctxt, dst, ctxt->mode); |
---|
| 817 | + u64 efer; |
---|
| 818 | + struct desc_struct cs; |
---|
| 819 | + u16 selector; |
---|
| 820 | + u32 base3; |
---|
| 821 | + |
---|
| 822 | + ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
| 823 | + |
---|
| 824 | + if (!(ctxt->ops->get_cr(ctxt, 0) & X86_CR0_PE)) { |
---|
| 825 | + /* Real mode. cpu must not have long mode active */ |
---|
| 826 | + if (efer & EFER_LMA) |
---|
| 827 | + return X86EMUL_UNHANDLEABLE; |
---|
| 828 | + ctxt->mode = X86EMUL_MODE_REAL; |
---|
| 829 | + return X86EMUL_CONTINUE; |
---|
| 830 | + } |
---|
| 831 | + |
---|
| 832 | + if (ctxt->eflags & X86_EFLAGS_VM) { |
---|
| 833 | + /* Protected/VM86 mode. cpu must not have long mode active */ |
---|
| 834 | + if (efer & EFER_LMA) |
---|
| 835 | + return X86EMUL_UNHANDLEABLE; |
---|
| 836 | + ctxt->mode = X86EMUL_MODE_VM86; |
---|
| 837 | + return X86EMUL_CONTINUE; |
---|
| 838 | + } |
---|
| 839 | + |
---|
| 840 | + if (!ctxt->ops->get_segment(ctxt, &selector, &cs, &base3, VCPU_SREG_CS)) |
---|
| 841 | + return X86EMUL_UNHANDLEABLE; |
---|
| 842 | + |
---|
| 843 | + if (efer & EFER_LMA) { |
---|
| 844 | + if (cs.l) { |
---|
| 845 | + /* Proper long mode */ |
---|
| 846 | + ctxt->mode = X86EMUL_MODE_PROT64; |
---|
| 847 | + } else if (cs.d) { |
---|
| 848 | + /* 32 bit compatibility mode*/ |
---|
| 849 | + ctxt->mode = X86EMUL_MODE_PROT32; |
---|
| 850 | + } else { |
---|
| 851 | + ctxt->mode = X86EMUL_MODE_PROT16; |
---|
| 852 | + } |
---|
| 853 | + } else { |
---|
| 854 | + /* Legacy 32 bit / 16 bit mode */ |
---|
| 855 | + ctxt->mode = cs.d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; |
---|
| 856 | + } |
---|
| 857 | + |
---|
| 858 | + return X86EMUL_CONTINUE; |
---|
782 | 859 | } |
---|
783 | 860 | |
---|
784 | | -static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst, |
---|
785 | | - const struct desc_struct *cs_desc) |
---|
| 861 | +static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) |
---|
786 | 862 | { |
---|
787 | | - enum x86emul_mode mode = ctxt->mode; |
---|
788 | | - int rc; |
---|
| 863 | + return assign_eip(ctxt, dst); |
---|
| 864 | +} |
---|
789 | 865 | |
---|
790 | | -#ifdef CONFIG_X86_64 |
---|
791 | | - if (ctxt->mode >= X86EMUL_MODE_PROT16) { |
---|
792 | | - if (cs_desc->l) { |
---|
793 | | - u64 efer = 0; |
---|
| 866 | +static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst) |
---|
| 867 | +{ |
---|
| 868 | + int rc = emulator_recalc_and_set_mode(ctxt); |
---|
794 | 869 | |
---|
795 | | - ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
796 | | - if (efer & EFER_LMA) |
---|
797 | | - mode = X86EMUL_MODE_PROT64; |
---|
798 | | - } else |
---|
799 | | - mode = X86EMUL_MODE_PROT32; /* temporary value */ |
---|
800 | | - } |
---|
801 | | -#endif |
---|
802 | | - if (mode == X86EMUL_MODE_PROT16 || mode == X86EMUL_MODE_PROT32) |
---|
803 | | - mode = cs_desc->d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; |
---|
804 | | - rc = assign_eip(ctxt, dst, mode); |
---|
805 | | - if (rc == X86EMUL_CONTINUE) |
---|
806 | | - ctxt->mode = mode; |
---|
807 | | - return rc; |
---|
| 870 | + if (rc != X86EMUL_CONTINUE) |
---|
| 871 | + return rc; |
---|
| 872 | + |
---|
| 873 | + return assign_eip(ctxt, dst); |
---|
808 | 874 | } |
---|
809 | 875 | |
---|
810 | 876 | static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) |
---|
.. | .. |
---|
1033 | 1099 | static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) |
---|
1034 | 1100 | { |
---|
1035 | 1101 | u8 rc; |
---|
1036 | | - void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf); |
---|
| 1102 | + void (*fop)(void) = (void *)em_setcc + SETCC_ALIGN * (condition & 0xf); |
---|
1037 | 1103 | |
---|
1038 | 1104 | flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF; |
---|
1039 | 1105 | asm("push %[flags]; popf; " CALL_NOSPEC |
---|
.. | .. |
---|
1059 | 1125 | } |
---|
1060 | 1126 | } |
---|
1061 | 1127 | |
---|
1062 | | -static void read_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, int reg) |
---|
| 1128 | +static void emulator_get_fpu(void) |
---|
1063 | 1129 | { |
---|
| 1130 | + fpregs_lock(); |
---|
| 1131 | + |
---|
| 1132 | + fpregs_assert_state_consistent(); |
---|
| 1133 | + if (test_thread_flag(TIF_NEED_FPU_LOAD)) |
---|
| 1134 | + switch_fpu_return(); |
---|
| 1135 | +} |
---|
| 1136 | + |
---|
| 1137 | +static void emulator_put_fpu(void) |
---|
| 1138 | +{ |
---|
| 1139 | + fpregs_unlock(); |
---|
| 1140 | +} |
---|
| 1141 | + |
---|
| 1142 | +static void read_sse_reg(sse128_t *data, int reg) |
---|
| 1143 | +{ |
---|
| 1144 | + emulator_get_fpu(); |
---|
1064 | 1145 | switch (reg) { |
---|
1065 | 1146 | case 0: asm("movdqa %%xmm0, %0" : "=m"(*data)); break; |
---|
1066 | 1147 | case 1: asm("movdqa %%xmm1, %0" : "=m"(*data)); break; |
---|
.. | .. |
---|
1082 | 1163 | #endif |
---|
1083 | 1164 | default: BUG(); |
---|
1084 | 1165 | } |
---|
| 1166 | + emulator_put_fpu(); |
---|
1085 | 1167 | } |
---|
1086 | 1168 | |
---|
1087 | | -static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, |
---|
1088 | | - int reg) |
---|
| 1169 | +static void write_sse_reg(sse128_t *data, int reg) |
---|
1089 | 1170 | { |
---|
| 1171 | + emulator_get_fpu(); |
---|
1090 | 1172 | switch (reg) { |
---|
1091 | 1173 | case 0: asm("movdqa %0, %%xmm0" : : "m"(*data)); break; |
---|
1092 | 1174 | case 1: asm("movdqa %0, %%xmm1" : : "m"(*data)); break; |
---|
.. | .. |
---|
1108 | 1190 | #endif |
---|
1109 | 1191 | default: BUG(); |
---|
1110 | 1192 | } |
---|
| 1193 | + emulator_put_fpu(); |
---|
1111 | 1194 | } |
---|
1112 | 1195 | |
---|
1113 | | -static void read_mmx_reg(struct x86_emulate_ctxt *ctxt, u64 *data, int reg) |
---|
| 1196 | +static void read_mmx_reg(u64 *data, int reg) |
---|
1114 | 1197 | { |
---|
| 1198 | + emulator_get_fpu(); |
---|
1115 | 1199 | switch (reg) { |
---|
1116 | 1200 | case 0: asm("movq %%mm0, %0" : "=m"(*data)); break; |
---|
1117 | 1201 | case 1: asm("movq %%mm1, %0" : "=m"(*data)); break; |
---|
.. | .. |
---|
1123 | 1207 | case 7: asm("movq %%mm7, %0" : "=m"(*data)); break; |
---|
1124 | 1208 | default: BUG(); |
---|
1125 | 1209 | } |
---|
| 1210 | + emulator_put_fpu(); |
---|
1126 | 1211 | } |
---|
1127 | 1212 | |
---|
1128 | | -static void write_mmx_reg(struct x86_emulate_ctxt *ctxt, u64 *data, int reg) |
---|
| 1213 | +static void write_mmx_reg(u64 *data, int reg) |
---|
1129 | 1214 | { |
---|
| 1215 | + emulator_get_fpu(); |
---|
1130 | 1216 | switch (reg) { |
---|
1131 | 1217 | case 0: asm("movq %0, %%mm0" : : "m"(*data)); break; |
---|
1132 | 1218 | case 1: asm("movq %0, %%mm1" : : "m"(*data)); break; |
---|
.. | .. |
---|
1138 | 1224 | case 7: asm("movq %0, %%mm7" : : "m"(*data)); break; |
---|
1139 | 1225 | default: BUG(); |
---|
1140 | 1226 | } |
---|
| 1227 | + emulator_put_fpu(); |
---|
1141 | 1228 | } |
---|
1142 | 1229 | |
---|
1143 | 1230 | static int em_fninit(struct x86_emulate_ctxt *ctxt) |
---|
.. | .. |
---|
1145 | 1232 | if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM)) |
---|
1146 | 1233 | return emulate_nm(ctxt); |
---|
1147 | 1234 | |
---|
| 1235 | + emulator_get_fpu(); |
---|
1148 | 1236 | asm volatile("fninit"); |
---|
| 1237 | + emulator_put_fpu(); |
---|
1149 | 1238 | return X86EMUL_CONTINUE; |
---|
1150 | 1239 | } |
---|
1151 | 1240 | |
---|
.. | .. |
---|
1156 | 1245 | if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM)) |
---|
1157 | 1246 | return emulate_nm(ctxt); |
---|
1158 | 1247 | |
---|
| 1248 | + emulator_get_fpu(); |
---|
1159 | 1249 | asm volatile("fnstcw %0": "+m"(fcw)); |
---|
| 1250 | + emulator_put_fpu(); |
---|
1160 | 1251 | |
---|
1161 | 1252 | ctxt->dst.val = fcw; |
---|
1162 | 1253 | |
---|
.. | .. |
---|
1170 | 1261 | if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM)) |
---|
1171 | 1262 | return emulate_nm(ctxt); |
---|
1172 | 1263 | |
---|
| 1264 | + emulator_get_fpu(); |
---|
1173 | 1265 | asm volatile("fnstsw %0": "+m"(fsw)); |
---|
| 1266 | + emulator_put_fpu(); |
---|
1174 | 1267 | |
---|
1175 | 1268 | ctxt->dst.val = fsw; |
---|
1176 | 1269 | |
---|
.. | .. |
---|
1189 | 1282 | op->type = OP_XMM; |
---|
1190 | 1283 | op->bytes = 16; |
---|
1191 | 1284 | op->addr.xmm = reg; |
---|
1192 | | - read_sse_reg(ctxt, &op->vec_val, reg); |
---|
| 1285 | + read_sse_reg(&op->vec_val, reg); |
---|
1193 | 1286 | return; |
---|
1194 | 1287 | } |
---|
1195 | 1288 | if (ctxt->d & Mmx) { |
---|
.. | .. |
---|
1240 | 1333 | op->type = OP_XMM; |
---|
1241 | 1334 | op->bytes = 16; |
---|
1242 | 1335 | op->addr.xmm = ctxt->modrm_rm; |
---|
1243 | | - read_sse_reg(ctxt, &op->vec_val, ctxt->modrm_rm); |
---|
| 1336 | + read_sse_reg(&op->vec_val, ctxt->modrm_rm); |
---|
1244 | 1337 | return rc; |
---|
1245 | 1338 | } |
---|
1246 | 1339 | if (ctxt->d & Mmx) { |
---|
.. | .. |
---|
1509 | 1602 | return emulate_gp(ctxt, index << 3 | 0x2); |
---|
1510 | 1603 | |
---|
1511 | 1604 | addr = dt.address + index * 8; |
---|
1512 | | - return linear_read_system(ctxt, addr, desc, sizeof *desc); |
---|
| 1605 | + return linear_read_system(ctxt, addr, desc, sizeof(*desc)); |
---|
1513 | 1606 | } |
---|
1514 | 1607 | |
---|
1515 | 1608 | static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt, |
---|
.. | .. |
---|
1522 | 1615 | struct desc_struct desc; |
---|
1523 | 1616 | u16 sel; |
---|
1524 | 1617 | |
---|
1525 | | - memset (dt, 0, sizeof *dt); |
---|
| 1618 | + memset(dt, 0, sizeof(*dt)); |
---|
1526 | 1619 | if (!ops->get_segment(ctxt, &sel, &desc, &base3, |
---|
1527 | 1620 | VCPU_SREG_LDTR)) |
---|
1528 | 1621 | return; |
---|
.. | .. |
---|
1586 | 1679 | if (rc != X86EMUL_CONTINUE) |
---|
1587 | 1680 | return rc; |
---|
1588 | 1681 | |
---|
1589 | | - return linear_write_system(ctxt, addr, desc, sizeof *desc); |
---|
| 1682 | + return linear_write_system(ctxt, addr, desc, sizeof(*desc)); |
---|
1590 | 1683 | } |
---|
1591 | 1684 | |
---|
1592 | 1685 | static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, |
---|
.. | .. |
---|
1604 | 1697 | u16 dummy; |
---|
1605 | 1698 | u32 base3 = 0; |
---|
1606 | 1699 | |
---|
1607 | | - memset(&seg_desc, 0, sizeof seg_desc); |
---|
| 1700 | + memset(&seg_desc, 0, sizeof(seg_desc)); |
---|
1608 | 1701 | |
---|
1609 | 1702 | if (ctxt->mode == X86EMUL_MODE_REAL) { |
---|
1610 | 1703 | /* set real mode segment descriptor (keep limit etc. for |
---|
.. | .. |
---|
1669 | 1762 | goto exception; |
---|
1670 | 1763 | } |
---|
1671 | 1764 | |
---|
1672 | | - if (!seg_desc.p) { |
---|
1673 | | - err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR; |
---|
1674 | | - goto exception; |
---|
1675 | | - } |
---|
1676 | | - |
---|
1677 | 1765 | dpl = seg_desc.dpl; |
---|
1678 | 1766 | |
---|
1679 | 1767 | switch (seg) { |
---|
.. | .. |
---|
1713 | 1801 | case VCPU_SREG_TR: |
---|
1714 | 1802 | if (seg_desc.s || (seg_desc.type != 1 && seg_desc.type != 9)) |
---|
1715 | 1803 | goto exception; |
---|
1716 | | - old_desc = seg_desc; |
---|
1717 | | - seg_desc.type |= 2; /* busy */ |
---|
1718 | | - ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, |
---|
1719 | | - sizeof(seg_desc), &ctxt->exception); |
---|
1720 | | - if (ret != X86EMUL_CONTINUE) |
---|
1721 | | - return ret; |
---|
1722 | 1804 | break; |
---|
1723 | 1805 | case VCPU_SREG_LDTR: |
---|
1724 | 1806 | if (seg_desc.s || seg_desc.type != 2) |
---|
.. | .. |
---|
1737 | 1819 | break; |
---|
1738 | 1820 | } |
---|
1739 | 1821 | |
---|
| 1822 | + if (!seg_desc.p) { |
---|
| 1823 | + err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR; |
---|
| 1824 | + goto exception; |
---|
| 1825 | + } |
---|
| 1826 | + |
---|
1740 | 1827 | if (seg_desc.s) { |
---|
1741 | 1828 | /* mark segment as accessed */ |
---|
1742 | 1829 | if (!(seg_desc.type & 1)) { |
---|
.. | .. |
---|
1751 | 1838 | if (ret != X86EMUL_CONTINUE) |
---|
1752 | 1839 | return ret; |
---|
1753 | 1840 | if (emul_is_noncanonical_address(get_desc_base(&seg_desc) | |
---|
1754 | | - ((u64)base3 << 32), ctxt)) |
---|
1755 | | - return emulate_gp(ctxt, 0); |
---|
| 1841 | + ((u64)base3 << 32), ctxt)) |
---|
| 1842 | + return emulate_gp(ctxt, err_code); |
---|
| 1843 | + } |
---|
| 1844 | + |
---|
| 1845 | + if (seg == VCPU_SREG_TR) { |
---|
| 1846 | + old_desc = seg_desc; |
---|
| 1847 | + seg_desc.type |= 2; /* busy */ |
---|
| 1848 | + ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, |
---|
| 1849 | + sizeof(seg_desc), &ctxt->exception); |
---|
| 1850 | + if (ret != X86EMUL_CONTINUE) |
---|
| 1851 | + return ret; |
---|
1756 | 1852 | } |
---|
1757 | 1853 | load: |
---|
1758 | 1854 | ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg); |
---|
.. | .. |
---|
1817 | 1913 | op->bytes * op->count); |
---|
1818 | 1914 | break; |
---|
1819 | 1915 | case OP_XMM: |
---|
1820 | | - write_sse_reg(ctxt, &op->vec_val, op->addr.xmm); |
---|
| 1916 | + write_sse_reg(&op->vec_val, op->addr.xmm); |
---|
1821 | 1917 | break; |
---|
1822 | 1918 | case OP_MM: |
---|
1823 | | - write_mmx_reg(ctxt, &op->mm_val, op->addr.mm); |
---|
| 1919 | + write_mmx_reg(&op->mm_val, op->addr.mm); |
---|
1824 | 1920 | break; |
---|
1825 | 1921 | case OP_NONE: |
---|
1826 | 1922 | /* no writeback */ |
---|
.. | .. |
---|
1972 | 2068 | if (rc != X86EMUL_CONTINUE) |
---|
1973 | 2069 | return rc; |
---|
1974 | 2070 | |
---|
1975 | | - if (ctxt->modrm_reg == VCPU_SREG_SS) |
---|
| 2071 | + if (seg == VCPU_SREG_SS) |
---|
1976 | 2072 | ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS; |
---|
1977 | 2073 | if (ctxt->op_bytes > 2) |
---|
1978 | 2074 | rsp_increment(ctxt, ctxt->op_bytes - 2); |
---|
.. | .. |
---|
2189 | 2285 | if (rc != X86EMUL_CONTINUE) |
---|
2190 | 2286 | return rc; |
---|
2191 | 2287 | |
---|
2192 | | - rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); |
---|
| 2288 | + rc = assign_eip_far(ctxt, ctxt->src.val); |
---|
2193 | 2289 | /* Error handling is not implemented. */ |
---|
2194 | 2290 | if (rc != X86EMUL_CONTINUE) |
---|
2195 | 2291 | return X86EMUL_UNHANDLEABLE; |
---|
.. | .. |
---|
2270 | 2366 | &new_desc); |
---|
2271 | 2367 | if (rc != X86EMUL_CONTINUE) |
---|
2272 | 2368 | return rc; |
---|
2273 | | - rc = assign_eip_far(ctxt, eip, &new_desc); |
---|
| 2369 | + rc = assign_eip_far(ctxt, eip); |
---|
2274 | 2370 | /* Error handling is not implemented. */ |
---|
2275 | 2371 | if (rc != X86EMUL_CONTINUE) |
---|
2276 | 2372 | return X86EMUL_UNHANDLEABLE; |
---|
.. | .. |
---|
2332 | 2428 | static int emulator_has_longmode(struct x86_emulate_ctxt *ctxt) |
---|
2333 | 2429 | { |
---|
2334 | 2430 | #ifdef CONFIG_X86_64 |
---|
2335 | | - u32 eax, ebx, ecx, edx; |
---|
2336 | | - |
---|
2337 | | - eax = 0x80000001; |
---|
2338 | | - ecx = 0; |
---|
2339 | | - ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
2340 | | - return edx & bit(X86_FEATURE_LM); |
---|
| 2431 | + return ctxt->ops->guest_has_long_mode(ctxt); |
---|
2341 | 2432 | #else |
---|
2342 | 2433 | return false; |
---|
2343 | 2434 | #endif |
---|
2344 | 2435 | } |
---|
2345 | | - |
---|
2346 | | -#define GET_SMSTATE(type, smbase, offset) \ |
---|
2347 | | - ({ \ |
---|
2348 | | - type __val; \ |
---|
2349 | | - int r = ctxt->ops->read_phys(ctxt, smbase + offset, &__val, \ |
---|
2350 | | - sizeof(__val)); \ |
---|
2351 | | - if (r != X86EMUL_CONTINUE) \ |
---|
2352 | | - return X86EMUL_UNHANDLEABLE; \ |
---|
2353 | | - __val; \ |
---|
2354 | | - }) |
---|
2355 | 2436 | |
---|
2356 | 2437 | static void rsm_set_desc_flags(struct desc_struct *desc, u32 flags) |
---|
2357 | 2438 | { |
---|
.. | .. |
---|
2365 | 2446 | desc->type = (flags >> 8) & 15; |
---|
2366 | 2447 | } |
---|
2367 | 2448 | |
---|
2368 | | -static int rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) |
---|
| 2449 | +static int rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, const char *smstate, |
---|
| 2450 | + int n) |
---|
2369 | 2451 | { |
---|
2370 | 2452 | struct desc_struct desc; |
---|
2371 | 2453 | int offset; |
---|
2372 | 2454 | u16 selector; |
---|
2373 | 2455 | |
---|
2374 | | - selector = GET_SMSTATE(u32, smbase, 0x7fa8 + n * 4); |
---|
| 2456 | + selector = GET_SMSTATE(u32, smstate, 0x7fa8 + n * 4); |
---|
2375 | 2457 | |
---|
2376 | 2458 | if (n < 3) |
---|
2377 | 2459 | offset = 0x7f84 + n * 12; |
---|
2378 | 2460 | else |
---|
2379 | 2461 | offset = 0x7f2c + (n - 3) * 12; |
---|
2380 | 2462 | |
---|
2381 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, offset + 8)); |
---|
2382 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, offset + 4)); |
---|
2383 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, offset)); |
---|
| 2463 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, offset + 8)); |
---|
| 2464 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, offset + 4)); |
---|
| 2465 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, offset)); |
---|
2384 | 2466 | ctxt->ops->set_segment(ctxt, selector, &desc, 0, n); |
---|
2385 | 2467 | return X86EMUL_CONTINUE; |
---|
2386 | 2468 | } |
---|
2387 | 2469 | |
---|
2388 | 2470 | #ifdef CONFIG_X86_64 |
---|
2389 | | -static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) |
---|
| 2471 | +static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, const char *smstate, |
---|
| 2472 | + int n) |
---|
2390 | 2473 | { |
---|
2391 | 2474 | struct desc_struct desc; |
---|
2392 | 2475 | int offset; |
---|
.. | .. |
---|
2395 | 2478 | |
---|
2396 | 2479 | offset = 0x7e00 + n * 16; |
---|
2397 | 2480 | |
---|
2398 | | - selector = GET_SMSTATE(u16, smbase, offset); |
---|
2399 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u16, smbase, offset + 2) << 8); |
---|
2400 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, offset + 4)); |
---|
2401 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, offset + 8)); |
---|
2402 | | - base3 = GET_SMSTATE(u32, smbase, offset + 12); |
---|
| 2481 | + selector = GET_SMSTATE(u16, smstate, offset); |
---|
| 2482 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u16, smstate, offset + 2) << 8); |
---|
| 2483 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, offset + 4)); |
---|
| 2484 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, offset + 8)); |
---|
| 2485 | + base3 = GET_SMSTATE(u32, smstate, offset + 12); |
---|
2403 | 2486 | |
---|
2404 | 2487 | ctxt->ops->set_segment(ctxt, selector, &desc, base3, n); |
---|
2405 | 2488 | return X86EMUL_CONTINUE; |
---|
.. | .. |
---|
2451 | 2534 | return X86EMUL_CONTINUE; |
---|
2452 | 2535 | } |
---|
2453 | 2536 | |
---|
2454 | | -static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) |
---|
| 2537 | +static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, |
---|
| 2538 | + const char *smstate) |
---|
2455 | 2539 | { |
---|
2456 | 2540 | struct desc_struct desc; |
---|
2457 | 2541 | struct desc_ptr dt; |
---|
.. | .. |
---|
2459 | 2543 | u32 val, cr0, cr3, cr4; |
---|
2460 | 2544 | int i; |
---|
2461 | 2545 | |
---|
2462 | | - cr0 = GET_SMSTATE(u32, smbase, 0x7ffc); |
---|
2463 | | - cr3 = GET_SMSTATE(u32, smbase, 0x7ff8); |
---|
2464 | | - ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED; |
---|
2465 | | - ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0); |
---|
| 2546 | + cr0 = GET_SMSTATE(u32, smstate, 0x7ffc); |
---|
| 2547 | + cr3 = GET_SMSTATE(u32, smstate, 0x7ff8); |
---|
| 2548 | + ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7ff4) | X86_EFLAGS_FIXED; |
---|
| 2549 | + ctxt->_eip = GET_SMSTATE(u32, smstate, 0x7ff0); |
---|
2466 | 2550 | |
---|
2467 | 2551 | for (i = 0; i < 8; i++) |
---|
2468 | | - *reg_write(ctxt, i) = GET_SMSTATE(u32, smbase, 0x7fd0 + i * 4); |
---|
| 2552 | + *reg_write(ctxt, i) = GET_SMSTATE(u32, smstate, 0x7fd0 + i * 4); |
---|
2469 | 2553 | |
---|
2470 | | - val = GET_SMSTATE(u32, smbase, 0x7fcc); |
---|
2471 | | - ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1); |
---|
2472 | | - val = GET_SMSTATE(u32, smbase, 0x7fc8); |
---|
2473 | | - ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1); |
---|
| 2554 | + val = GET_SMSTATE(u32, smstate, 0x7fcc); |
---|
2474 | 2555 | |
---|
2475 | | - selector = GET_SMSTATE(u32, smbase, 0x7fc4); |
---|
2476 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7f64)); |
---|
2477 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7f60)); |
---|
2478 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7f5c)); |
---|
| 2556 | + if (ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1)) |
---|
| 2557 | + return X86EMUL_UNHANDLEABLE; |
---|
| 2558 | + |
---|
| 2559 | + val = GET_SMSTATE(u32, smstate, 0x7fc8); |
---|
| 2560 | + |
---|
| 2561 | + if (ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1)) |
---|
| 2562 | + return X86EMUL_UNHANDLEABLE; |
---|
| 2563 | + |
---|
| 2564 | + selector = GET_SMSTATE(u32, smstate, 0x7fc4); |
---|
| 2565 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7f64)); |
---|
| 2566 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7f60)); |
---|
| 2567 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7f5c)); |
---|
2479 | 2568 | ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_TR); |
---|
2480 | 2569 | |
---|
2481 | | - selector = GET_SMSTATE(u32, smbase, 0x7fc0); |
---|
2482 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7f80)); |
---|
2483 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7f7c)); |
---|
2484 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7f78)); |
---|
| 2570 | + selector = GET_SMSTATE(u32, smstate, 0x7fc0); |
---|
| 2571 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7f80)); |
---|
| 2572 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7f7c)); |
---|
| 2573 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7f78)); |
---|
2485 | 2574 | ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_LDTR); |
---|
2486 | 2575 | |
---|
2487 | | - dt.address = GET_SMSTATE(u32, smbase, 0x7f74); |
---|
2488 | | - dt.size = GET_SMSTATE(u32, smbase, 0x7f70); |
---|
| 2576 | + dt.address = GET_SMSTATE(u32, smstate, 0x7f74); |
---|
| 2577 | + dt.size = GET_SMSTATE(u32, smstate, 0x7f70); |
---|
2489 | 2578 | ctxt->ops->set_gdt(ctxt, &dt); |
---|
2490 | 2579 | |
---|
2491 | | - dt.address = GET_SMSTATE(u32, smbase, 0x7f58); |
---|
2492 | | - dt.size = GET_SMSTATE(u32, smbase, 0x7f54); |
---|
| 2580 | + dt.address = GET_SMSTATE(u32, smstate, 0x7f58); |
---|
| 2581 | + dt.size = GET_SMSTATE(u32, smstate, 0x7f54); |
---|
2493 | 2582 | ctxt->ops->set_idt(ctxt, &dt); |
---|
2494 | 2583 | |
---|
2495 | 2584 | for (i = 0; i < 6; i++) { |
---|
2496 | | - int r = rsm_load_seg_32(ctxt, smbase, i); |
---|
| 2585 | + int r = rsm_load_seg_32(ctxt, smstate, i); |
---|
2497 | 2586 | if (r != X86EMUL_CONTINUE) |
---|
2498 | 2587 | return r; |
---|
2499 | 2588 | } |
---|
2500 | 2589 | |
---|
2501 | | - cr4 = GET_SMSTATE(u32, smbase, 0x7f14); |
---|
| 2590 | + cr4 = GET_SMSTATE(u32, smstate, 0x7f14); |
---|
2502 | 2591 | |
---|
2503 | | - ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8)); |
---|
| 2592 | + ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smstate, 0x7ef8)); |
---|
2504 | 2593 | |
---|
2505 | 2594 | return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4); |
---|
2506 | 2595 | } |
---|
2507 | 2596 | |
---|
2508 | 2597 | #ifdef CONFIG_X86_64 |
---|
2509 | | -static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) |
---|
| 2598 | +static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, |
---|
| 2599 | + const char *smstate) |
---|
2510 | 2600 | { |
---|
2511 | 2601 | struct desc_struct desc; |
---|
2512 | 2602 | struct desc_ptr dt; |
---|
.. | .. |
---|
2516 | 2606 | int i, r; |
---|
2517 | 2607 | |
---|
2518 | 2608 | for (i = 0; i < 16; i++) |
---|
2519 | | - *reg_write(ctxt, i) = GET_SMSTATE(u64, smbase, 0x7ff8 - i * 8); |
---|
| 2609 | + *reg_write(ctxt, i) = GET_SMSTATE(u64, smstate, 0x7ff8 - i * 8); |
---|
2520 | 2610 | |
---|
2521 | | - ctxt->_eip = GET_SMSTATE(u64, smbase, 0x7f78); |
---|
2522 | | - ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7f70) | X86_EFLAGS_FIXED; |
---|
| 2611 | + ctxt->_eip = GET_SMSTATE(u64, smstate, 0x7f78); |
---|
| 2612 | + ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7f70) | X86_EFLAGS_FIXED; |
---|
2523 | 2613 | |
---|
2524 | | - val = GET_SMSTATE(u32, smbase, 0x7f68); |
---|
2525 | | - ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1); |
---|
2526 | | - val = GET_SMSTATE(u32, smbase, 0x7f60); |
---|
2527 | | - ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1); |
---|
| 2614 | + val = GET_SMSTATE(u64, smstate, 0x7f68); |
---|
2528 | 2615 | |
---|
2529 | | - cr0 = GET_SMSTATE(u64, smbase, 0x7f58); |
---|
2530 | | - cr3 = GET_SMSTATE(u64, smbase, 0x7f50); |
---|
2531 | | - cr4 = GET_SMSTATE(u64, smbase, 0x7f48); |
---|
2532 | | - ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00)); |
---|
2533 | | - val = GET_SMSTATE(u64, smbase, 0x7ed0); |
---|
2534 | | - ctxt->ops->set_msr(ctxt, MSR_EFER, val & ~EFER_LMA); |
---|
| 2616 | + if (ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1)) |
---|
| 2617 | + return X86EMUL_UNHANDLEABLE; |
---|
2535 | 2618 | |
---|
2536 | | - selector = GET_SMSTATE(u32, smbase, 0x7e90); |
---|
2537 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7e92) << 8); |
---|
2538 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7e94)); |
---|
2539 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7e98)); |
---|
2540 | | - base3 = GET_SMSTATE(u32, smbase, 0x7e9c); |
---|
| 2619 | + val = GET_SMSTATE(u64, smstate, 0x7f60); |
---|
| 2620 | + |
---|
| 2621 | + if (ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1)) |
---|
| 2622 | + return X86EMUL_UNHANDLEABLE; |
---|
| 2623 | + |
---|
| 2624 | + cr0 = GET_SMSTATE(u64, smstate, 0x7f58); |
---|
| 2625 | + cr3 = GET_SMSTATE(u64, smstate, 0x7f50); |
---|
| 2626 | + cr4 = GET_SMSTATE(u64, smstate, 0x7f48); |
---|
| 2627 | + ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smstate, 0x7f00)); |
---|
| 2628 | + val = GET_SMSTATE(u64, smstate, 0x7ed0); |
---|
| 2629 | + |
---|
| 2630 | + if (ctxt->ops->set_msr(ctxt, MSR_EFER, val & ~EFER_LMA)) |
---|
| 2631 | + return X86EMUL_UNHANDLEABLE; |
---|
| 2632 | + |
---|
| 2633 | + selector = GET_SMSTATE(u32, smstate, 0x7e90); |
---|
| 2634 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7e92) << 8); |
---|
| 2635 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7e94)); |
---|
| 2636 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7e98)); |
---|
| 2637 | + base3 = GET_SMSTATE(u32, smstate, 0x7e9c); |
---|
2541 | 2638 | ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_TR); |
---|
2542 | 2639 | |
---|
2543 | | - dt.size = GET_SMSTATE(u32, smbase, 0x7e84); |
---|
2544 | | - dt.address = GET_SMSTATE(u64, smbase, 0x7e88); |
---|
| 2640 | + dt.size = GET_SMSTATE(u32, smstate, 0x7e84); |
---|
| 2641 | + dt.address = GET_SMSTATE(u64, smstate, 0x7e88); |
---|
2545 | 2642 | ctxt->ops->set_idt(ctxt, &dt); |
---|
2546 | 2643 | |
---|
2547 | | - selector = GET_SMSTATE(u32, smbase, 0x7e70); |
---|
2548 | | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7e72) << 8); |
---|
2549 | | - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7e74)); |
---|
2550 | | - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7e78)); |
---|
2551 | | - base3 = GET_SMSTATE(u32, smbase, 0x7e7c); |
---|
| 2644 | + selector = GET_SMSTATE(u32, smstate, 0x7e70); |
---|
| 2645 | + rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7e72) << 8); |
---|
| 2646 | + set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7e74)); |
---|
| 2647 | + set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7e78)); |
---|
| 2648 | + base3 = GET_SMSTATE(u32, smstate, 0x7e7c); |
---|
2552 | 2649 | ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_LDTR); |
---|
2553 | 2650 | |
---|
2554 | | - dt.size = GET_SMSTATE(u32, smbase, 0x7e64); |
---|
2555 | | - dt.address = GET_SMSTATE(u64, smbase, 0x7e68); |
---|
| 2651 | + dt.size = GET_SMSTATE(u32, smstate, 0x7e64); |
---|
| 2652 | + dt.address = GET_SMSTATE(u64, smstate, 0x7e68); |
---|
2556 | 2653 | ctxt->ops->set_gdt(ctxt, &dt); |
---|
2557 | 2654 | |
---|
2558 | 2655 | r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4); |
---|
.. | .. |
---|
2560 | 2657 | return r; |
---|
2561 | 2658 | |
---|
2562 | 2659 | for (i = 0; i < 6; i++) { |
---|
2563 | | - r = rsm_load_seg_64(ctxt, smbase, i); |
---|
| 2660 | + r = rsm_load_seg_64(ctxt, smstate, i); |
---|
2564 | 2661 | if (r != X86EMUL_CONTINUE) |
---|
2565 | 2662 | return r; |
---|
2566 | 2663 | } |
---|
.. | .. |
---|
2572 | 2669 | static int em_rsm(struct x86_emulate_ctxt *ctxt) |
---|
2573 | 2670 | { |
---|
2574 | 2671 | unsigned long cr0, cr4, efer; |
---|
| 2672 | + char buf[512]; |
---|
2575 | 2673 | u64 smbase; |
---|
2576 | 2674 | int ret; |
---|
2577 | 2675 | |
---|
2578 | 2676 | if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0) |
---|
2579 | 2677 | return emulate_ud(ctxt); |
---|
| 2678 | + |
---|
| 2679 | + smbase = ctxt->ops->get_smbase(ctxt); |
---|
| 2680 | + |
---|
| 2681 | + ret = ctxt->ops->read_phys(ctxt, smbase + 0xfe00, buf, sizeof(buf)); |
---|
| 2682 | + if (ret != X86EMUL_CONTINUE) |
---|
| 2683 | + return X86EMUL_UNHANDLEABLE; |
---|
| 2684 | + |
---|
| 2685 | + if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) |
---|
| 2686 | + ctxt->ops->set_nmi_mask(ctxt, false); |
---|
| 2687 | + |
---|
| 2688 | + ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) & |
---|
| 2689 | + ~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK)); |
---|
2580 | 2690 | |
---|
2581 | 2691 | /* |
---|
2582 | 2692 | * Get back to real mode, to prepare a safe state in which to load |
---|
.. | .. |
---|
2614 | 2724 | ctxt->ops->set_msr(ctxt, MSR_EFER, efer); |
---|
2615 | 2725 | } |
---|
2616 | 2726 | |
---|
2617 | | - smbase = ctxt->ops->get_smbase(ctxt); |
---|
2618 | | - |
---|
2619 | 2727 | /* |
---|
2620 | 2728 | * Give pre_leave_smm() a chance to make ISA-specific changes to the |
---|
2621 | 2729 | * vCPU state (e.g. enter guest mode) before loading state from the SMM |
---|
2622 | 2730 | * state-save area. |
---|
2623 | 2731 | */ |
---|
2624 | | - if (ctxt->ops->pre_leave_smm(ctxt, smbase)) |
---|
| 2732 | + if (ctxt->ops->pre_leave_smm(ctxt, buf)) |
---|
2625 | 2733 | return X86EMUL_UNHANDLEABLE; |
---|
2626 | 2734 | |
---|
2627 | 2735 | #ifdef CONFIG_X86_64 |
---|
2628 | 2736 | if (emulator_has_longmode(ctxt)) |
---|
2629 | | - ret = rsm_load_state_64(ctxt, smbase + 0x8000); |
---|
| 2737 | + ret = rsm_load_state_64(ctxt, buf); |
---|
2630 | 2738 | else |
---|
2631 | 2739 | #endif |
---|
2632 | | - ret = rsm_load_state_32(ctxt, smbase + 0x8000); |
---|
| 2740 | + ret = rsm_load_state_32(ctxt, buf); |
---|
2633 | 2741 | |
---|
2634 | 2742 | if (ret != X86EMUL_CONTINUE) { |
---|
2635 | 2743 | /* FIXME: should triple fault */ |
---|
2636 | 2744 | return X86EMUL_UNHANDLEABLE; |
---|
2637 | 2745 | } |
---|
2638 | 2746 | |
---|
2639 | | - if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) |
---|
2640 | | - ctxt->ops->set_nmi_mask(ctxt, false); |
---|
| 2747 | + ctxt->ops->post_leave_smm(ctxt); |
---|
2641 | 2748 | |
---|
2642 | | - ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) & |
---|
2643 | | - ~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK)); |
---|
2644 | 2749 | return X86EMUL_CONTINUE; |
---|
2645 | 2750 | } |
---|
2646 | 2751 | |
---|
.. | .. |
---|
2676 | 2781 | u32 eax, ebx, ecx, edx; |
---|
2677 | 2782 | |
---|
2678 | 2783 | eax = ecx = 0; |
---|
2679 | | - ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
2680 | | - return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx |
---|
2681 | | - && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx |
---|
2682 | | - && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx; |
---|
| 2784 | + ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, true); |
---|
| 2785 | + return is_guest_vendor_intel(ebx, ecx, edx); |
---|
2683 | 2786 | } |
---|
2684 | 2787 | |
---|
2685 | 2788 | static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) |
---|
.. | .. |
---|
2696 | 2799 | |
---|
2697 | 2800 | eax = 0x00000000; |
---|
2698 | 2801 | ecx = 0x00000000; |
---|
2699 | | - ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
| 2802 | + ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, true); |
---|
2700 | 2803 | /* |
---|
2701 | | - * Intel ("GenuineIntel") |
---|
2702 | | - * remark: Intel CPUs only support "syscall" in 64bit |
---|
2703 | | - * longmode. Also an 64bit guest with a |
---|
2704 | | - * 32bit compat-app running will #UD !! While this |
---|
2705 | | - * behaviour can be fixed (by emulating) into AMD |
---|
2706 | | - * response - CPUs of AMD can't behave like Intel. |
---|
| 2804 | + * remark: Intel CPUs only support "syscall" in 64bit longmode. Also a |
---|
| 2805 | + * 64bit guest with a 32bit compat-app running will #UD !! While this |
---|
| 2806 | + * behaviour can be fixed (by emulating) into AMD response - CPUs of |
---|
| 2807 | + * AMD can't behave like Intel. |
---|
2707 | 2808 | */ |
---|
2708 | | - if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && |
---|
2709 | | - ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && |
---|
2710 | | - edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) |
---|
| 2809 | + if (is_guest_vendor_intel(ebx, ecx, edx)) |
---|
2711 | 2810 | return false; |
---|
2712 | 2811 | |
---|
2713 | | - /* AMD ("AuthenticAMD") */ |
---|
2714 | | - if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && |
---|
2715 | | - ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && |
---|
2716 | | - edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) |
---|
| 2812 | + if (is_guest_vendor_amd(ebx, ecx, edx) || |
---|
| 2813 | + is_guest_vendor_hygon(ebx, ecx, edx)) |
---|
2717 | 2814 | return true; |
---|
2718 | 2815 | |
---|
2719 | | - /* AMD ("AMDisbetter!") */ |
---|
2720 | | - if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && |
---|
2721 | | - ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && |
---|
2722 | | - edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) |
---|
2723 | | - return true; |
---|
2724 | | - |
---|
2725 | | - /* default: (not Intel, not AMD), apply Intel's stricter rules... */ |
---|
| 2816 | + /* |
---|
| 2817 | + * default: (not Intel, not AMD, not Hygon), apply Intel's |
---|
| 2818 | + * stricter rules... |
---|
| 2819 | + */ |
---|
2726 | 2820 | return false; |
---|
2727 | 2821 | } |
---|
2728 | 2822 | |
---|
.. | .. |
---|
2743 | 2837 | return emulate_ud(ctxt); |
---|
2744 | 2838 | |
---|
2745 | 2839 | ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
2746 | | - setup_syscalls_segments(ctxt, &cs, &ss); |
---|
2747 | | - |
---|
2748 | 2840 | if (!(efer & EFER_SCE)) |
---|
2749 | 2841 | return emulate_ud(ctxt); |
---|
2750 | 2842 | |
---|
| 2843 | + setup_syscalls_segments(ctxt, &cs, &ss); |
---|
2751 | 2844 | ops->get_msr(ctxt, MSR_STAR, &msr_data); |
---|
2752 | 2845 | msr_data >>= 32; |
---|
2753 | 2846 | cs_sel = (u16)(msr_data & 0xfffc); |
---|
.. | .. |
---|
2811 | 2904 | if (ctxt->mode == X86EMUL_MODE_PROT64) |
---|
2812 | 2905 | return X86EMUL_UNHANDLEABLE; |
---|
2813 | 2906 | |
---|
2814 | | - setup_syscalls_segments(ctxt, &cs, &ss); |
---|
2815 | | - |
---|
2816 | 2907 | ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); |
---|
2817 | 2908 | if ((msr_data & 0xfffc) == 0x0) |
---|
2818 | 2909 | return emulate_gp(ctxt, 0); |
---|
2819 | 2910 | |
---|
| 2911 | + setup_syscalls_segments(ctxt, &cs, &ss); |
---|
2820 | 2912 | ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF); |
---|
2821 | 2913 | cs_sel = (u16)msr_data & ~SEGMENT_RPL_MASK; |
---|
2822 | 2914 | ss_sel = cs_sel + 8; |
---|
.. | .. |
---|
2834 | 2926 | ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data); |
---|
2835 | 2927 | *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data : |
---|
2836 | 2928 | (u32)msr_data; |
---|
| 2929 | + if (efer & EFER_LMA) |
---|
| 2930 | + ctxt->mode = X86EMUL_MODE_PROT64; |
---|
2837 | 2931 | |
---|
2838 | 2932 | return X86EMUL_CONTINUE; |
---|
2839 | 2933 | } |
---|
.. | .. |
---|
2892 | 2986 | ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); |
---|
2893 | 2987 | |
---|
2894 | 2988 | ctxt->_eip = rdx; |
---|
| 2989 | + ctxt->mode = usermode; |
---|
2895 | 2990 | *reg_write(ctxt, VCPU_REGS_RSP) = rcx; |
---|
2896 | 2991 | |
---|
2897 | 2992 | return X86EMUL_CONTINUE; |
---|
.. | .. |
---|
2983 | 3078 | case 0xa4: /* movsb */ |
---|
2984 | 3079 | case 0xa5: /* movsd/w */ |
---|
2985 | 3080 | *reg_rmw(ctxt, VCPU_REGS_RSI) &= (u32)-1; |
---|
2986 | | - /* fall through */ |
---|
| 3081 | + fallthrough; |
---|
2987 | 3082 | case 0xaa: /* stosb */ |
---|
2988 | 3083 | case 0xab: /* stosd/w */ |
---|
2989 | 3084 | *reg_rmw(ctxt, VCPU_REGS_RDI) &= (u32)-1; |
---|
.. | .. |
---|
3077 | 3172 | int ret; |
---|
3078 | 3173 | u32 new_tss_base = get_desc_base(new_desc); |
---|
3079 | 3174 | |
---|
3080 | | - ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); |
---|
| 3175 | + ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof(tss_seg)); |
---|
3081 | 3176 | if (ret != X86EMUL_CONTINUE) |
---|
3082 | 3177 | return ret; |
---|
3083 | 3178 | |
---|
3084 | 3179 | save_state_to_tss16(ctxt, &tss_seg); |
---|
3085 | 3180 | |
---|
3086 | | - ret = linear_write_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); |
---|
| 3181 | + ret = linear_write_system(ctxt, old_tss_base, &tss_seg, sizeof(tss_seg)); |
---|
3087 | 3182 | if (ret != X86EMUL_CONTINUE) |
---|
3088 | 3183 | return ret; |
---|
3089 | 3184 | |
---|
3090 | | - ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg); |
---|
| 3185 | + ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof(tss_seg)); |
---|
3091 | 3186 | if (ret != X86EMUL_CONTINUE) |
---|
3092 | 3187 | return ret; |
---|
3093 | 3188 | |
---|
.. | .. |
---|
3096 | 3191 | |
---|
3097 | 3192 | ret = linear_write_system(ctxt, new_tss_base, |
---|
3098 | 3193 | &tss_seg.prev_task_link, |
---|
3099 | | - sizeof tss_seg.prev_task_link); |
---|
| 3194 | + sizeof(tss_seg.prev_task_link)); |
---|
3100 | 3195 | if (ret != X86EMUL_CONTINUE) |
---|
3101 | 3196 | return ret; |
---|
3102 | 3197 | } |
---|
.. | .. |
---|
3218 | 3313 | u32 eip_offset = offsetof(struct tss_segment_32, eip); |
---|
3219 | 3314 | u32 ldt_sel_offset = offsetof(struct tss_segment_32, ldt_selector); |
---|
3220 | 3315 | |
---|
3221 | | - ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); |
---|
| 3316 | + ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof(tss_seg)); |
---|
3222 | 3317 | if (ret != X86EMUL_CONTINUE) |
---|
3223 | 3318 | return ret; |
---|
3224 | 3319 | |
---|
.. | .. |
---|
3230 | 3325 | if (ret != X86EMUL_CONTINUE) |
---|
3231 | 3326 | return ret; |
---|
3232 | 3327 | |
---|
3233 | | - ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg); |
---|
| 3328 | + ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof(tss_seg)); |
---|
3234 | 3329 | if (ret != X86EMUL_CONTINUE) |
---|
3235 | 3330 | return ret; |
---|
3236 | 3331 | |
---|
.. | .. |
---|
3239 | 3334 | |
---|
3240 | 3335 | ret = linear_write_system(ctxt, new_tss_base, |
---|
3241 | 3336 | &tss_seg.prev_task_link, |
---|
3242 | | - sizeof tss_seg.prev_task_link); |
---|
| 3337 | + sizeof(tss_seg.prev_task_link)); |
---|
3243 | 3338 | if (ret != X86EMUL_CONTINUE) |
---|
3244 | 3339 | return ret; |
---|
3245 | 3340 | } |
---|
.. | .. |
---|
3488 | 3583 | if (rc != X86EMUL_CONTINUE) |
---|
3489 | 3584 | return rc; |
---|
3490 | 3585 | |
---|
3491 | | - rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); |
---|
| 3586 | + rc = assign_eip_far(ctxt, ctxt->src.val); |
---|
3492 | 3587 | if (rc != X86EMUL_CONTINUE) |
---|
3493 | 3588 | goto fail; |
---|
3494 | 3589 | |
---|
.. | .. |
---|
3560 | 3655 | { |
---|
3561 | 3656 | u64 tsc_aux = 0; |
---|
3562 | 3657 | |
---|
3563 | | - if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux)) |
---|
| 3658 | + if (!ctxt->ops->guest_has_rdpid(ctxt)) |
---|
3564 | 3659 | return emulate_ud(ctxt); |
---|
| 3660 | + |
---|
| 3661 | + ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux); |
---|
3565 | 3662 | ctxt->dst.val = tsc_aux; |
---|
3566 | 3663 | return X86EMUL_CONTINUE; |
---|
3567 | 3664 | } |
---|
.. | .. |
---|
3593 | 3690 | return X86EMUL_CONTINUE; |
---|
3594 | 3691 | } |
---|
3595 | 3692 | |
---|
3596 | | -#define FFL(x) bit(X86_FEATURE_##x) |
---|
3597 | | - |
---|
3598 | 3693 | static int em_movbe(struct x86_emulate_ctxt *ctxt) |
---|
3599 | 3694 | { |
---|
3600 | | - u32 ebx, ecx, edx, eax = 1; |
---|
3601 | 3695 | u16 tmp; |
---|
3602 | 3696 | |
---|
3603 | | - /* |
---|
3604 | | - * Check MOVBE is set in the guest-visible CPUID leaf. |
---|
3605 | | - */ |
---|
3606 | | - ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
3607 | | - if (!(ecx & FFL(MOVBE))) |
---|
| 3697 | + if (!ctxt->ops->guest_has_movbe(ctxt)) |
---|
3608 | 3698 | return emulate_ud(ctxt); |
---|
3609 | 3699 | |
---|
3610 | 3700 | switch (ctxt->op_bytes) { |
---|
.. | .. |
---|
3635 | 3725 | |
---|
3636 | 3726 | static int em_cr_write(struct x86_emulate_ctxt *ctxt) |
---|
3637 | 3727 | { |
---|
3638 | | - if (ctxt->ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val)) |
---|
| 3728 | + int cr_num = ctxt->modrm_reg; |
---|
| 3729 | + int r; |
---|
| 3730 | + |
---|
| 3731 | + if (ctxt->ops->set_cr(ctxt, cr_num, ctxt->src.val)) |
---|
3639 | 3732 | return emulate_gp(ctxt, 0); |
---|
3640 | 3733 | |
---|
3641 | 3734 | /* Disable writeback. */ |
---|
3642 | 3735 | ctxt->dst.type = OP_NONE; |
---|
| 3736 | + |
---|
| 3737 | + if (cr_num == 0) { |
---|
| 3738 | + /* |
---|
| 3739 | + * CR0 write might have updated CR0.PE and/or CR0.PG |
---|
| 3740 | + * which can affect the cpu's execution mode. |
---|
| 3741 | + */ |
---|
| 3742 | + r = emulator_recalc_and_set_mode(ctxt); |
---|
| 3743 | + if (r != X86EMUL_CONTINUE) |
---|
| 3744 | + return r; |
---|
| 3745 | + } |
---|
| 3746 | + |
---|
3643 | 3747 | return X86EMUL_CONTINUE; |
---|
3644 | 3748 | } |
---|
3645 | 3749 | |
---|
.. | .. |
---|
3663 | 3767 | |
---|
3664 | 3768 | static int em_wrmsr(struct x86_emulate_ctxt *ctxt) |
---|
3665 | 3769 | { |
---|
| 3770 | + u64 msr_index = reg_read(ctxt, VCPU_REGS_RCX); |
---|
3666 | 3771 | u64 msr_data; |
---|
| 3772 | + int r; |
---|
3667 | 3773 | |
---|
3668 | 3774 | msr_data = (u32)reg_read(ctxt, VCPU_REGS_RAX) |
---|
3669 | 3775 | | ((u64)reg_read(ctxt, VCPU_REGS_RDX) << 32); |
---|
3670 | | - if (ctxt->ops->set_msr(ctxt, reg_read(ctxt, VCPU_REGS_RCX), msr_data)) |
---|
| 3776 | + r = ctxt->ops->set_msr(ctxt, msr_index, msr_data); |
---|
| 3777 | + |
---|
| 3778 | + if (r == X86EMUL_IO_NEEDED) |
---|
| 3779 | + return r; |
---|
| 3780 | + |
---|
| 3781 | + if (r > 0) |
---|
3671 | 3782 | return emulate_gp(ctxt, 0); |
---|
3672 | 3783 | |
---|
3673 | | - return X86EMUL_CONTINUE; |
---|
| 3784 | + return r < 0 ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; |
---|
3674 | 3785 | } |
---|
3675 | 3786 | |
---|
3676 | 3787 | static int em_rdmsr(struct x86_emulate_ctxt *ctxt) |
---|
3677 | 3788 | { |
---|
| 3789 | + u64 msr_index = reg_read(ctxt, VCPU_REGS_RCX); |
---|
3678 | 3790 | u64 msr_data; |
---|
| 3791 | + int r; |
---|
3679 | 3792 | |
---|
3680 | | - if (ctxt->ops->get_msr(ctxt, reg_read(ctxt, VCPU_REGS_RCX), &msr_data)) |
---|
| 3793 | + r = ctxt->ops->get_msr(ctxt, msr_index, &msr_data); |
---|
| 3794 | + |
---|
| 3795 | + if (r == X86EMUL_IO_NEEDED) |
---|
| 3796 | + return r; |
---|
| 3797 | + |
---|
| 3798 | + if (r) |
---|
3681 | 3799 | return emulate_gp(ctxt, 0); |
---|
3682 | 3800 | |
---|
3683 | 3801 | *reg_write(ctxt, VCPU_REGS_RAX) = (u32)msr_data; |
---|
.. | .. |
---|
3945 | 4063 | |
---|
3946 | 4064 | eax = reg_read(ctxt, VCPU_REGS_RAX); |
---|
3947 | 4065 | ecx = reg_read(ctxt, VCPU_REGS_RCX); |
---|
3948 | | - ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, true); |
---|
| 4066 | + ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
3949 | 4067 | *reg_write(ctxt, VCPU_REGS_RAX) = eax; |
---|
3950 | 4068 | *reg_write(ctxt, VCPU_REGS_RBX) = ebx; |
---|
3951 | 4069 | *reg_write(ctxt, VCPU_REGS_RCX) = ecx; |
---|
.. | .. |
---|
4008 | 4126 | |
---|
4009 | 4127 | static int check_fxsr(struct x86_emulate_ctxt *ctxt) |
---|
4010 | 4128 | { |
---|
4011 | | - u32 eax = 1, ebx, ecx = 0, edx; |
---|
4012 | | - |
---|
4013 | | - ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx, false); |
---|
4014 | | - if (!(edx & FFL(FXSR))) |
---|
| 4129 | + if (!ctxt->ops->guest_has_fxsr(ctxt)) |
---|
4015 | 4130 | return emulate_ud(ctxt); |
---|
4016 | 4131 | |
---|
4017 | 4132 | if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM)) |
---|
.. | .. |
---|
4073 | 4188 | if (rc != X86EMUL_CONTINUE) |
---|
4074 | 4189 | return rc; |
---|
4075 | 4190 | |
---|
| 4191 | + emulator_get_fpu(); |
---|
| 4192 | + |
---|
4076 | 4193 | rc = asm_safe("fxsave %[fx]", , [fx] "+m"(fx_state)); |
---|
| 4194 | + |
---|
| 4195 | + emulator_put_fpu(); |
---|
4077 | 4196 | |
---|
4078 | 4197 | if (rc != X86EMUL_CONTINUE) |
---|
4079 | 4198 | return rc; |
---|
.. | .. |
---|
4117 | 4236 | if (rc != X86EMUL_CONTINUE) |
---|
4118 | 4237 | return rc; |
---|
4119 | 4238 | |
---|
| 4239 | + emulator_get_fpu(); |
---|
| 4240 | + |
---|
4120 | 4241 | if (size < __fxstate_size(16)) { |
---|
4121 | 4242 | rc = fxregs_fixup(&fx_state, size); |
---|
4122 | 4243 | if (rc != X86EMUL_CONTINUE) |
---|
.. | .. |
---|
4132 | 4253 | rc = asm_safe("fxrstor %[fx]", : [fx] "m"(fx_state)); |
---|
4133 | 4254 | |
---|
4134 | 4255 | out: |
---|
| 4256 | + emulator_put_fpu(); |
---|
| 4257 | + |
---|
4135 | 4258 | return rc; |
---|
| 4259 | +} |
---|
| 4260 | + |
---|
| 4261 | +static int em_xsetbv(struct x86_emulate_ctxt *ctxt) |
---|
| 4262 | +{ |
---|
| 4263 | + u32 eax, ecx, edx; |
---|
| 4264 | + |
---|
| 4265 | + eax = reg_read(ctxt, VCPU_REGS_RAX); |
---|
| 4266 | + edx = reg_read(ctxt, VCPU_REGS_RDX); |
---|
| 4267 | + ecx = reg_read(ctxt, VCPU_REGS_RCX); |
---|
| 4268 | + |
---|
| 4269 | + if (ctxt->ops->set_xcr(ctxt, ecx, ((u64)edx << 32) | eax)) |
---|
| 4270 | + return emulate_gp(ctxt, 0); |
---|
| 4271 | + |
---|
| 4272 | + return X86EMUL_CONTINUE; |
---|
4136 | 4273 | } |
---|
4137 | 4274 | |
---|
4138 | 4275 | static bool valid_cr(int nr) |
---|
.. | .. |
---|
4147 | 4284 | } |
---|
4148 | 4285 | } |
---|
4149 | 4286 | |
---|
4150 | | -static int check_cr_read(struct x86_emulate_ctxt *ctxt) |
---|
| 4287 | +static int check_cr_access(struct x86_emulate_ctxt *ctxt) |
---|
4151 | 4288 | { |
---|
4152 | 4289 | if (!valid_cr(ctxt->modrm_reg)) |
---|
4153 | 4290 | return emulate_ud(ctxt); |
---|
4154 | | - |
---|
4155 | | - return X86EMUL_CONTINUE; |
---|
4156 | | -} |
---|
4157 | | - |
---|
4158 | | -static int check_cr_write(struct x86_emulate_ctxt *ctxt) |
---|
4159 | | -{ |
---|
4160 | | - u64 new_val = ctxt->src.val64; |
---|
4161 | | - int cr = ctxt->modrm_reg; |
---|
4162 | | - u64 efer = 0; |
---|
4163 | | - |
---|
4164 | | - static u64 cr_reserved_bits[] = { |
---|
4165 | | - 0xffffffff00000000ULL, |
---|
4166 | | - 0, 0, 0, /* CR3 checked later */ |
---|
4167 | | - CR4_RESERVED_BITS, |
---|
4168 | | - 0, 0, 0, |
---|
4169 | | - CR8_RESERVED_BITS, |
---|
4170 | | - }; |
---|
4171 | | - |
---|
4172 | | - if (!valid_cr(cr)) |
---|
4173 | | - return emulate_ud(ctxt); |
---|
4174 | | - |
---|
4175 | | - if (new_val & cr_reserved_bits[cr]) |
---|
4176 | | - return emulate_gp(ctxt, 0); |
---|
4177 | | - |
---|
4178 | | - switch (cr) { |
---|
4179 | | - case 0: { |
---|
4180 | | - u64 cr4; |
---|
4181 | | - if (((new_val & X86_CR0_PG) && !(new_val & X86_CR0_PE)) || |
---|
4182 | | - ((new_val & X86_CR0_NW) && !(new_val & X86_CR0_CD))) |
---|
4183 | | - return emulate_gp(ctxt, 0); |
---|
4184 | | - |
---|
4185 | | - cr4 = ctxt->ops->get_cr(ctxt, 4); |
---|
4186 | | - ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
4187 | | - |
---|
4188 | | - if ((new_val & X86_CR0_PG) && (efer & EFER_LME) && |
---|
4189 | | - !(cr4 & X86_CR4_PAE)) |
---|
4190 | | - return emulate_gp(ctxt, 0); |
---|
4191 | | - |
---|
4192 | | - break; |
---|
4193 | | - } |
---|
4194 | | - case 3: { |
---|
4195 | | - u64 rsvd = 0; |
---|
4196 | | - |
---|
4197 | | - ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
4198 | | - if (efer & EFER_LMA) { |
---|
4199 | | - u64 maxphyaddr; |
---|
4200 | | - u32 eax, ebx, ecx, edx; |
---|
4201 | | - |
---|
4202 | | - eax = 0x80000008; |
---|
4203 | | - ecx = 0; |
---|
4204 | | - if (ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, |
---|
4205 | | - &edx, false)) |
---|
4206 | | - maxphyaddr = eax & 0xff; |
---|
4207 | | - else |
---|
4208 | | - maxphyaddr = 36; |
---|
4209 | | - rsvd = rsvd_bits(maxphyaddr, 63); |
---|
4210 | | - if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_PCIDE) |
---|
4211 | | - rsvd &= ~X86_CR3_PCID_NOFLUSH; |
---|
4212 | | - } |
---|
4213 | | - |
---|
4214 | | - if (new_val & rsvd) |
---|
4215 | | - return emulate_gp(ctxt, 0); |
---|
4216 | | - |
---|
4217 | | - break; |
---|
4218 | | - } |
---|
4219 | | - case 4: { |
---|
4220 | | - ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); |
---|
4221 | | - |
---|
4222 | | - if ((efer & EFER_LMA) && !(new_val & X86_CR4_PAE)) |
---|
4223 | | - return emulate_gp(ctxt, 0); |
---|
4224 | | - |
---|
4225 | | - break; |
---|
4226 | | - } |
---|
4227 | | - } |
---|
4228 | 4291 | |
---|
4229 | 4292 | return X86EMUL_CONTINUE; |
---|
4230 | 4293 | } |
---|
.. | .. |
---|
4255 | 4318 | ulong dr6; |
---|
4256 | 4319 | |
---|
4257 | 4320 | ctxt->ops->get_dr(ctxt, 6, &dr6); |
---|
4258 | | - dr6 &= ~15; |
---|
| 4321 | + dr6 &= ~DR_TRAP_BITS; |
---|
4259 | 4322 | dr6 |= DR6_BD | DR6_RTM; |
---|
4260 | 4323 | ctxt->ops->set_dr(ctxt, 6, dr6); |
---|
4261 | 4324 | return emulate_db(ctxt); |
---|
.. | .. |
---|
4388 | 4451 | N, N, N, N, N, N, |
---|
4389 | 4452 | }; |
---|
4390 | 4453 | |
---|
| 4454 | +static const struct opcode group7_rm2[] = { |
---|
| 4455 | + N, |
---|
| 4456 | + II(ImplicitOps | Priv, em_xsetbv, xsetbv), |
---|
| 4457 | + N, N, N, N, N, N, |
---|
| 4458 | +}; |
---|
| 4459 | + |
---|
4391 | 4460 | static const struct opcode group7_rm3[] = { |
---|
4392 | 4461 | DIP(SrcNone | Prot | Priv, vmrun, check_svme_pa), |
---|
4393 | 4462 | II(SrcNone | Prot | EmulateOnUD, em_hypercall, vmmcall), |
---|
.. | .. |
---|
4477 | 4546 | }, { |
---|
4478 | 4547 | EXT(0, group7_rm0), |
---|
4479 | 4548 | EXT(0, group7_rm1), |
---|
4480 | | - N, EXT(0, group7_rm3), |
---|
| 4549 | + EXT(0, group7_rm2), |
---|
| 4550 | + EXT(0, group7_rm3), |
---|
4481 | 4551 | II(SrcNone | DstMem | Mov, em_smsw, smsw), N, |
---|
4482 | 4552 | II(SrcMem16 | Mov | Priv, em_lmsw, lmsw), |
---|
4483 | 4553 | EXT(0, group7_rm7), |
---|
.. | .. |
---|
4496 | 4566 | * from the register case of group9. |
---|
4497 | 4567 | */ |
---|
4498 | 4568 | static const struct gprefix pfx_0f_c7_7 = { |
---|
4499 | | - N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp), |
---|
| 4569 | + N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdpid), |
---|
4500 | 4570 | }; |
---|
4501 | 4571 | |
---|
4502 | 4572 | |
---|
.. | .. |
---|
4754 | 4824 | GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_10_0f_11), |
---|
4755 | 4825 | GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_10_0f_11), |
---|
4756 | 4826 | N, N, N, N, N, N, |
---|
4757 | | - D(ImplicitOps | ModRM | SrcMem | NoAccess), |
---|
4758 | | - N, N, N, N, N, N, D(ImplicitOps | ModRM | SrcMem | NoAccess), |
---|
| 4827 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 4 * prefetch + 4 * reserved NOP */ |
---|
| 4828 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N, |
---|
| 4829 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 8 * reserved NOP */ |
---|
| 4830 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 8 * reserved NOP */ |
---|
| 4831 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 8 * reserved NOP */ |
---|
| 4832 | + D(ImplicitOps | ModRM | SrcMem | NoAccess), /* NOP + 7 * reserved NOP */ |
---|
4759 | 4833 | /* 0x20 - 0x2F */ |
---|
4760 | | - DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read), |
---|
| 4834 | + DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_access), |
---|
4761 | 4835 | DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read), |
---|
4762 | 4836 | IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_cr_write, cr_write, |
---|
4763 | | - check_cr_write), |
---|
| 4837 | + check_cr_access), |
---|
4764 | 4838 | IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write, |
---|
4765 | 4839 | check_dr_write), |
---|
4766 | 4840 | N, N, N, N, |
---|
.. | .. |
---|
5124 | 5198 | else { |
---|
5125 | 5199 | rc = __do_insn_fetch_bytes(ctxt, 1); |
---|
5126 | 5200 | if (rc != X86EMUL_CONTINUE) |
---|
5127 | | - return rc; |
---|
| 5201 | + goto done; |
---|
5128 | 5202 | } |
---|
5129 | 5203 | |
---|
5130 | 5204 | switch (mode) { |
---|
.. | .. |
---|
5426 | 5500 | { |
---|
5427 | 5501 | int rc; |
---|
5428 | 5502 | |
---|
| 5503 | + emulator_get_fpu(); |
---|
5429 | 5504 | rc = asm_safe("fwait"); |
---|
| 5505 | + emulator_put_fpu(); |
---|
5430 | 5506 | |
---|
5431 | 5507 | if (unlikely(rc != X86EMUL_CONTINUE)) |
---|
5432 | 5508 | return emulate_exception(ctxt, MF_VECTOR, 0, false); |
---|
.. | .. |
---|
5434 | 5510 | return X86EMUL_CONTINUE; |
---|
5435 | 5511 | } |
---|
5436 | 5512 | |
---|
5437 | | -static void fetch_possible_mmx_operand(struct x86_emulate_ctxt *ctxt, |
---|
5438 | | - struct operand *op) |
---|
| 5513 | +static void fetch_possible_mmx_operand(struct operand *op) |
---|
5439 | 5514 | { |
---|
5440 | 5515 | if (op->type == OP_MM) |
---|
5441 | | - read_mmx_reg(ctxt, &op->mm_val, op->addr.mm); |
---|
| 5516 | + read_mmx_reg(&op->mm_val, op->addr.mm); |
---|
5442 | 5517 | } |
---|
5443 | 5518 | |
---|
5444 | | -static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)) |
---|
| 5519 | +static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop) |
---|
5445 | 5520 | { |
---|
5446 | 5521 | ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF; |
---|
5447 | 5522 | |
---|
.. | .. |
---|
5517 | 5592 | * Now that we know the fpu is exception safe, we can fetch |
---|
5518 | 5593 | * operands from it. |
---|
5519 | 5594 | */ |
---|
5520 | | - fetch_possible_mmx_operand(ctxt, &ctxt->src); |
---|
5521 | | - fetch_possible_mmx_operand(ctxt, &ctxt->src2); |
---|
| 5595 | + fetch_possible_mmx_operand(&ctxt->src); |
---|
| 5596 | + fetch_possible_mmx_operand(&ctxt->src2); |
---|
5522 | 5597 | if (!(ctxt->d & Mov)) |
---|
5523 | | - fetch_possible_mmx_operand(ctxt, &ctxt->dst); |
---|
| 5598 | + fetch_possible_mmx_operand(&ctxt->dst); |
---|
5524 | 5599 | } |
---|
5525 | 5600 | |
---|
5526 | 5601 | if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { |
---|
.. | .. |
---|
5619 | 5694 | ctxt->eflags &= ~X86_EFLAGS_RF; |
---|
5620 | 5695 | |
---|
5621 | 5696 | if (ctxt->execute) { |
---|
5622 | | - if (ctxt->d & Fastop) { |
---|
5623 | | - void (*fop)(struct fastop *) = (void *)ctxt->execute; |
---|
5624 | | - rc = fastop(ctxt, fop); |
---|
5625 | | - if (rc != X86EMUL_CONTINUE) |
---|
5626 | | - goto done; |
---|
5627 | | - goto writeback; |
---|
5628 | | - } |
---|
5629 | | - rc = ctxt->execute(ctxt); |
---|
| 5697 | + if (ctxt->d & Fastop) |
---|
| 5698 | + rc = fastop(ctxt, ctxt->fop); |
---|
| 5699 | + else |
---|
| 5700 | + rc = ctxt->execute(ctxt); |
---|
5630 | 5701 | if (rc != X86EMUL_CONTINUE) |
---|
5631 | 5702 | goto done; |
---|
5632 | 5703 | goto writeback; |
---|
.. | .. |
---|
5755 | 5826 | } |
---|
5756 | 5827 | |
---|
5757 | 5828 | ctxt->eip = ctxt->_eip; |
---|
| 5829 | + if (ctxt->mode != X86EMUL_MODE_PROT64) |
---|
| 5830 | + ctxt->eip = (u32)ctxt->_eip; |
---|
5758 | 5831 | |
---|
5759 | 5832 | done: |
---|
5760 | 5833 | if (rc == X86EMUL_PROPAGATE_FAULT) { |
---|