diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 21 | ||||
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 96 | ||||
-rw-r--r-- | include/asm-x86/kvm_x86_emulate.h | 10 |
3 files changed, 60 insertions, 67 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d1db5aa5c7f4..f726ba79fd3a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2126,27 +2126,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
2126 | ? X86EMUL_MODE_PROT64 : cs_db | 2126 | ? X86EMUL_MODE_PROT64 : cs_db |
2127 | ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; | 2127 | ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; |
2128 | 2128 | ||
2129 | if (vcpu->arch.emulate_ctxt.mode == X86EMUL_MODE_PROT64) { | ||
2130 | vcpu->arch.emulate_ctxt.cs_base = 0; | ||
2131 | vcpu->arch.emulate_ctxt.ds_base = 0; | ||
2132 | vcpu->arch.emulate_ctxt.es_base = 0; | ||
2133 | vcpu->arch.emulate_ctxt.ss_base = 0; | ||
2134 | } else { | ||
2135 | vcpu->arch.emulate_ctxt.cs_base = | ||
2136 | get_segment_base(vcpu, VCPU_SREG_CS); | ||
2137 | vcpu->arch.emulate_ctxt.ds_base = | ||
2138 | get_segment_base(vcpu, VCPU_SREG_DS); | ||
2139 | vcpu->arch.emulate_ctxt.es_base = | ||
2140 | get_segment_base(vcpu, VCPU_SREG_ES); | ||
2141 | vcpu->arch.emulate_ctxt.ss_base = | ||
2142 | get_segment_base(vcpu, VCPU_SREG_SS); | ||
2143 | } | ||
2144 | |||
2145 | vcpu->arch.emulate_ctxt.gs_base = | ||
2146 | get_segment_base(vcpu, VCPU_SREG_GS); | ||
2147 | vcpu->arch.emulate_ctxt.fs_base = | ||
2148 | get_segment_base(vcpu, VCPU_SREG_FS); | ||
2149 | |||
2150 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); | 2129 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); |
2151 | 2130 | ||
2152 | /* Reject the instructions other than VMCALL/VMMCALL when | 2131 | /* Reject the instructions other than VMCALL/VMMCALL when |
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 38926b7da64a..18ca25c2d4a4 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c | |||
@@ -522,6 +522,39 @@ static inline void jmp_rel(struct decode_cache *c, int rel) | |||
522 | register_address_increment(c, &c->eip, rel); | 522 | register_address_increment(c, &c->eip, rel); |
523 | } | 523 | } |
524 | 524 | ||
525 | static void set_seg_override(struct decode_cache *c, int seg) | ||
526 | { | ||
527 | c->has_seg_override = true; | ||
528 | c->seg_override = seg; | ||
529 | } | ||
530 | |||
531 | static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg) | ||
532 | { | ||
533 | if (ctxt->mode == X86EMUL_MODE_PROT64 && seg < VCPU_SREG_FS) | ||
534 | return 0; | ||
535 | |||
536 | return kvm_x86_ops->get_segment_base(ctxt->vcpu, seg); | ||
537 | } | ||
538 | |||
539 | static unsigned long seg_override_base(struct x86_emulate_ctxt *ctxt, | ||
540 | struct decode_cache *c) | ||
541 | { | ||
542 | if (!c->has_seg_override) | ||
543 | return 0; | ||
544 | |||
545 | return seg_base(ctxt, c->seg_override); | ||
546 | } | ||
547 | |||
548 | static unsigned long es_base(struct x86_emulate_ctxt *ctxt) | ||
549 | { | ||
550 | return seg_base(ctxt, VCPU_SREG_ES); | ||
551 | } | ||
552 | |||
553 | static unsigned long ss_base(struct x86_emulate_ctxt *ctxt) | ||
554 | { | ||
555 | return seg_base(ctxt, VCPU_SREG_SS); | ||
556 | } | ||
557 | |||
525 | static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, | 558 | static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, |
526 | struct x86_emulate_ops *ops, | 559 | struct x86_emulate_ops *ops, |
527 | unsigned long linear, u8 *dest) | 560 | unsigned long linear, u8 *dest) |
@@ -735,8 +768,8 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, | |||
735 | } | 768 | } |
736 | if (c->modrm_rm == 2 || c->modrm_rm == 3 || | 769 | if (c->modrm_rm == 2 || c->modrm_rm == 3 || |
737 | (c->modrm_rm == 6 && c->modrm_mod != 0)) | 770 | (c->modrm_rm == 6 && c->modrm_mod != 0)) |
738 | if (!c->override_base) | 771 | if (!c->has_seg_override) |
739 | c->override_base = &ctxt->ss_base; | 772 | set_seg_override(c, VCPU_SREG_SS); |
740 | c->modrm_ea = (u16)c->modrm_ea; | 773 | c->modrm_ea = (u16)c->modrm_ea; |
741 | } else { | 774 | } else { |
742 | /* 32/64-bit ModR/M decode. */ | 775 | /* 32/64-bit ModR/M decode. */ |
@@ -807,6 +840,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
807 | 840 | ||
808 | memset(c, 0, sizeof(struct decode_cache)); | 841 | memset(c, 0, sizeof(struct decode_cache)); |
809 | c->eip = ctxt->vcpu->arch.rip; | 842 | c->eip = ctxt->vcpu->arch.rip; |
843 | ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS); | ||
810 | memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); | 844 | memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); |
811 | 845 | ||
812 | switch (mode) { | 846 | switch (mode) { |
@@ -845,23 +879,15 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
845 | /* switch between 2/4 bytes */ | 879 | /* switch between 2/4 bytes */ |
846 | c->ad_bytes = def_ad_bytes ^ 6; | 880 | c->ad_bytes = def_ad_bytes ^ 6; |
847 | break; | 881 | break; |
882 | case 0x26: /* ES override */ | ||
848 | case 0x2e: /* CS override */ | 883 | case 0x2e: /* CS override */ |
849 | c->override_base = &ctxt->cs_base; | 884 | case 0x36: /* SS override */ |
850 | break; | ||
851 | case 0x3e: /* DS override */ | 885 | case 0x3e: /* DS override */ |
852 | c->override_base = &ctxt->ds_base; | 886 | set_seg_override(c, (c->b >> 3) & 3); |
853 | break; | ||
854 | case 0x26: /* ES override */ | ||
855 | c->override_base = &ctxt->es_base; | ||
856 | break; | 887 | break; |
857 | case 0x64: /* FS override */ | 888 | case 0x64: /* FS override */ |
858 | c->override_base = &ctxt->fs_base; | ||
859 | break; | ||
860 | case 0x65: /* GS override */ | 889 | case 0x65: /* GS override */ |
861 | c->override_base = &ctxt->gs_base; | 890 | set_seg_override(c, c->b & 7); |
862 | break; | ||
863 | case 0x36: /* SS override */ | ||
864 | c->override_base = &ctxt->ss_base; | ||
865 | break; | 891 | break; |
866 | case 0x40 ... 0x4f: /* REX */ | 892 | case 0x40 ... 0x4f: /* REX */ |
867 | if (mode != X86EMUL_MODE_PROT64) | 893 | if (mode != X86EMUL_MODE_PROT64) |
@@ -933,15 +959,11 @@ done_prefixes: | |||
933 | if (rc) | 959 | if (rc) |
934 | goto done; | 960 | goto done; |
935 | 961 | ||
936 | if (!c->override_base) | 962 | if (!c->has_seg_override) |
937 | c->override_base = &ctxt->ds_base; | 963 | set_seg_override(c, VCPU_SREG_DS); |
938 | if (mode == X86EMUL_MODE_PROT64 && | ||
939 | c->override_base != &ctxt->fs_base && | ||
940 | c->override_base != &ctxt->gs_base) | ||
941 | c->override_base = NULL; | ||
942 | 964 | ||
943 | if (c->override_base && !(!c->twobyte && c->b == 0x8d)) | 965 | if (!(!c->twobyte && c->b == 0x8d)) |
944 | c->modrm_ea += *c->override_base; | 966 | c->modrm_ea += seg_override_base(ctxt, c); |
945 | 967 | ||
946 | if (c->ad_bytes != 8) | 968 | if (c->ad_bytes != 8) |
947 | c->modrm_ea = (u32)c->modrm_ea; | 969 | c->modrm_ea = (u32)c->modrm_ea; |
@@ -1043,7 +1065,7 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt) | |||
1043 | c->dst.bytes = c->op_bytes; | 1065 | c->dst.bytes = c->op_bytes; |
1044 | c->dst.val = c->src.val; | 1066 | c->dst.val = c->src.val; |
1045 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes); | 1067 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes); |
1046 | c->dst.ptr = (void *) register_address(c, ctxt->ss_base, | 1068 | c->dst.ptr = (void *) register_address(c, ss_base(ctxt), |
1047 | c->regs[VCPU_REGS_RSP]); | 1069 | c->regs[VCPU_REGS_RSP]); |
1048 | } | 1070 | } |
1049 | 1071 | ||
@@ -1053,7 +1075,7 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, | |||
1053 | struct decode_cache *c = &ctxt->decode; | 1075 | struct decode_cache *c = &ctxt->decode; |
1054 | int rc; | 1076 | int rc; |
1055 | 1077 | ||
1056 | rc = ops->read_std(register_address(c, ctxt->ss_base, | 1078 | rc = ops->read_std(register_address(c, ss_base(ctxt), |
1057 | c->regs[VCPU_REGS_RSP]), | 1079 | c->regs[VCPU_REGS_RSP]), |
1058 | &c->dst.val, c->dst.bytes, ctxt->vcpu); | 1080 | &c->dst.val, c->dst.bytes, ctxt->vcpu); |
1059 | if (rc != 0) | 1081 | if (rc != 0) |
@@ -1375,11 +1397,11 @@ special_insn: | |||
1375 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], | 1397 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], |
1376 | -c->op_bytes); | 1398 | -c->op_bytes); |
1377 | c->dst.ptr = (void *) register_address( | 1399 | c->dst.ptr = (void *) register_address( |
1378 | c, ctxt->ss_base, c->regs[VCPU_REGS_RSP]); | 1400 | c, ss_base(ctxt), c->regs[VCPU_REGS_RSP]); |
1379 | break; | 1401 | break; |
1380 | case 0x58 ... 0x5f: /* pop reg */ | 1402 | case 0x58 ... 0x5f: /* pop reg */ |
1381 | pop_instruction: | 1403 | pop_instruction: |
1382 | if ((rc = ops->read_std(register_address(c, ctxt->ss_base, | 1404 | if ((rc = ops->read_std(register_address(c, ss_base(ctxt), |
1383 | c->regs[VCPU_REGS_RSP]), c->dst.ptr, | 1405 | c->regs[VCPU_REGS_RSP]), c->dst.ptr, |
1384 | c->op_bytes, ctxt->vcpu)) != 0) | 1406 | c->op_bytes, ctxt->vcpu)) != 0) |
1385 | goto done; | 1407 | goto done; |
@@ -1405,7 +1427,7 @@ special_insn: | |||
1405 | c->rep_prefix ? | 1427 | c->rep_prefix ? |
1406 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, | 1428 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, |
1407 | (ctxt->eflags & EFLG_DF), | 1429 | (ctxt->eflags & EFLG_DF), |
1408 | register_address(c, ctxt->es_base, | 1430 | register_address(c, es_base(ctxt), |
1409 | c->regs[VCPU_REGS_RDI]), | 1431 | c->regs[VCPU_REGS_RDI]), |
1410 | c->rep_prefix, | 1432 | c->rep_prefix, |
1411 | c->regs[VCPU_REGS_RDX]) == 0) { | 1433 | c->regs[VCPU_REGS_RDX]) == 0) { |
@@ -1421,9 +1443,8 @@ special_insn: | |||
1421 | c->rep_prefix ? | 1443 | c->rep_prefix ? |
1422 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, | 1444 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, |
1423 | (ctxt->eflags & EFLG_DF), | 1445 | (ctxt->eflags & EFLG_DF), |
1424 | register_address(c, c->override_base ? | 1446 | register_address(c, |
1425 | *c->override_base : | 1447 | seg_override_base(ctxt, c), |
1426 | ctxt->ds_base, | ||
1427 | c->regs[VCPU_REGS_RSI]), | 1448 | c->regs[VCPU_REGS_RSI]), |
1428 | c->rep_prefix, | 1449 | c->rep_prefix, |
1429 | c->regs[VCPU_REGS_RDX]) == 0) { | 1450 | c->regs[VCPU_REGS_RDX]) == 0) { |
@@ -1559,11 +1580,10 @@ special_insn: | |||
1559 | c->dst.type = OP_MEM; | 1580 | c->dst.type = OP_MEM; |
1560 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1581 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
1561 | c->dst.ptr = (unsigned long *)register_address(c, | 1582 | c->dst.ptr = (unsigned long *)register_address(c, |
1562 | ctxt->es_base, | 1583 | es_base(ctxt), |
1563 | c->regs[VCPU_REGS_RDI]); | 1584 | c->regs[VCPU_REGS_RDI]); |
1564 | if ((rc = ops->read_emulated(register_address(c, | 1585 | if ((rc = ops->read_emulated(register_address(c, |
1565 | c->override_base ? *c->override_base : | 1586 | seg_override_base(ctxt, c), |
1566 | ctxt->ds_base, | ||
1567 | c->regs[VCPU_REGS_RSI]), | 1587 | c->regs[VCPU_REGS_RSI]), |
1568 | &c->dst.val, | 1588 | &c->dst.val, |
1569 | c->dst.bytes, ctxt->vcpu)) != 0) | 1589 | c->dst.bytes, ctxt->vcpu)) != 0) |
@@ -1579,8 +1599,7 @@ special_insn: | |||
1579 | c->src.type = OP_NONE; /* Disable writeback. */ | 1599 | c->src.type = OP_NONE; /* Disable writeback. */ |
1580 | c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1600 | c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
1581 | c->src.ptr = (unsigned long *)register_address(c, | 1601 | c->src.ptr = (unsigned long *)register_address(c, |
1582 | c->override_base ? *c->override_base : | 1602 | seg_override_base(ctxt, c), |
1583 | ctxt->ds_base, | ||
1584 | c->regs[VCPU_REGS_RSI]); | 1603 | c->regs[VCPU_REGS_RSI]); |
1585 | if ((rc = ops->read_emulated((unsigned long)c->src.ptr, | 1604 | if ((rc = ops->read_emulated((unsigned long)c->src.ptr, |
1586 | &c->src.val, | 1605 | &c->src.val, |
@@ -1591,7 +1610,7 @@ special_insn: | |||
1591 | c->dst.type = OP_NONE; /* Disable writeback. */ | 1610 | c->dst.type = OP_NONE; /* Disable writeback. */ |
1592 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1611 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
1593 | c->dst.ptr = (unsigned long *)register_address(c, | 1612 | c->dst.ptr = (unsigned long *)register_address(c, |
1594 | ctxt->es_base, | 1613 | es_base(ctxt), |
1595 | c->regs[VCPU_REGS_RDI]); | 1614 | c->regs[VCPU_REGS_RDI]); |
1596 | if ((rc = ops->read_emulated((unsigned long)c->dst.ptr, | 1615 | if ((rc = ops->read_emulated((unsigned long)c->dst.ptr, |
1597 | &c->dst.val, | 1616 | &c->dst.val, |
@@ -1615,7 +1634,7 @@ special_insn: | |||
1615 | c->dst.type = OP_MEM; | 1634 | c->dst.type = OP_MEM; |
1616 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1635 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
1617 | c->dst.ptr = (unsigned long *)register_address(c, | 1636 | c->dst.ptr = (unsigned long *)register_address(c, |
1618 | ctxt->es_base, | 1637 | es_base(ctxt), |
1619 | c->regs[VCPU_REGS_RDI]); | 1638 | c->regs[VCPU_REGS_RDI]); |
1620 | c->dst.val = c->regs[VCPU_REGS_RAX]; | 1639 | c->dst.val = c->regs[VCPU_REGS_RAX]; |
1621 | register_address_increment(c, &c->regs[VCPU_REGS_RDI], | 1640 | register_address_increment(c, &c->regs[VCPU_REGS_RDI], |
@@ -1627,8 +1646,7 @@ special_insn: | |||
1627 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1646 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
1628 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; | 1647 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; |
1629 | if ((rc = ops->read_emulated(register_address(c, | 1648 | if ((rc = ops->read_emulated(register_address(c, |
1630 | c->override_base ? *c->override_base : | 1649 | seg_override_base(ctxt, c), |
1631 | ctxt->ds_base, | ||
1632 | c->regs[VCPU_REGS_RSI]), | 1650 | c->regs[VCPU_REGS_RSI]), |
1633 | &c->dst.val, | 1651 | &c->dst.val, |
1634 | c->dst.bytes, | 1652 | c->dst.bytes, |
diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h index 9fda4b35e195..4e8c1e48d91d 100644 --- a/include/asm-x86/kvm_x86_emulate.h +++ b/include/asm-x86/kvm_x86_emulate.h | |||
@@ -124,7 +124,8 @@ struct decode_cache { | |||
124 | u8 rex_prefix; | 124 | u8 rex_prefix; |
125 | struct operand src; | 125 | struct operand src; |
126 | struct operand dst; | 126 | struct operand dst; |
127 | unsigned long *override_base; | 127 | bool has_seg_override; |
128 | u8 seg_override; | ||
128 | unsigned int d; | 129 | unsigned int d; |
129 | unsigned long regs[NR_VCPU_REGS]; | 130 | unsigned long regs[NR_VCPU_REGS]; |
130 | unsigned long eip; | 131 | unsigned long eip; |
@@ -151,12 +152,7 @@ struct x86_emulate_ctxt { | |||
151 | /* Emulated execution mode, represented by an X86EMUL_MODE value. */ | 152 | /* Emulated execution mode, represented by an X86EMUL_MODE value. */ |
152 | int mode; | 153 | int mode; |
153 | 154 | ||
154 | unsigned long cs_base; | 155 | u32 cs_base; |
155 | unsigned long ds_base; | ||
156 | unsigned long es_base; | ||
157 | unsigned long ss_base; | ||
158 | unsigned long gs_base; | ||
159 | unsigned long fs_base; | ||
160 | 156 | ||
161 | /* decode cache */ | 157 | /* decode cache */ |
162 | 158 | ||