aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorLaurent Vivier <Laurent.Vivier@bull.net>2007-08-05 03:36:40 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:23 -0400
commite70669abd4e60dfea3ac1639848e20e2b8dd1255 (patch)
tree4625f787efdf5f586514cd6306e045a97edb490e /drivers/kvm/vmx.c
parent9fdaaac38e8c8a63c6383b807b91fea2d51da95d (diff)
KVM: Cleanup string I/O instruction emulation
Both vmx and svm decode the I/O instructions, and both botch the job, requiring the instruction prefixes to be fetched in order to completely decode the instruction. So, if we see a string I/O instruction, use the x86 emulator to decode it, as it already has all the prefix decoding machinery. This patch defines ins/outs opcodes in x86_emulate.c and calls emulate_instruction() from io_interception() (svm.c) and from handle_io() (vmx.c). It removes all vmx/svm prefix instruction decoders (get_addr_size(), io_get_override(), io_address(), get_io_count()) Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c76
1 files changed, 12 insertions, 64 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 30c627d3b21d..044722bc1a7f 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1763,82 +1763,30 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1763 return 0; 1763 return 0;
1764} 1764}
1765 1765
1766static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
1767{
1768 u64 inst;
1769 gva_t rip;
1770 int countr_size;
1771 int i;
1772
1773 if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) {
1774 countr_size = 2;
1775 } else {
1776 u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
1777
1778 countr_size = (cs_ar & AR_L_MASK) ? 8:
1779 (cs_ar & AR_DB_MASK) ? 4: 2;
1780 }
1781
1782 rip = vmcs_readl(GUEST_RIP);
1783 if (countr_size != 8)
1784 rip += vmcs_readl(GUEST_CS_BASE);
1785
1786 if (emulator_read_std(rip, &inst, sizeof(inst), vcpu) !=
1787 X86EMUL_CONTINUE)
1788 return 0;
1789
1790 for (i = 0; i < sizeof(inst); i++) {
1791 switch (((u8*)&inst)[i]) {
1792 case 0xf0:
1793 case 0xf2:
1794 case 0xf3:
1795 case 0x2e:
1796 case 0x36:
1797 case 0x3e:
1798 case 0x26:
1799 case 0x64:
1800 case 0x65:
1801 case 0x66:
1802 break;
1803 case 0x67:
1804 countr_size = (countr_size == 2) ? 4: (countr_size >> 1);
1805 default:
1806 goto done;
1807 }
1808 }
1809 return 0;
1810done:
1811 countr_size *= 8;
1812 *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
1813 //printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
1814 return 1;
1815}
1816
1817static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1766static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1818{ 1767{
1819 u64 exit_qualification; 1768 u64 exit_qualification;
1820 int size, down, in, string, rep; 1769 int size, down, in, string, rep;
1821 unsigned port; 1770 unsigned port;
1822 unsigned long count;
1823 gva_t address;
1824 1771
1825 ++vcpu->stat.io_exits; 1772 ++vcpu->stat.io_exits;
1826 exit_qualification = vmcs_read64(EXIT_QUALIFICATION); 1773 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
1827 in = (exit_qualification & 8) != 0;
1828 size = (exit_qualification & 7) + 1;
1829 string = (exit_qualification & 16) != 0; 1774 string = (exit_qualification & 16) != 0;
1775
1776 if (string) {
1777 if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
1778 return 0;
1779 return 1;
1780 }
1781
1782 size = (exit_qualification & 7) + 1;
1783 in = (exit_qualification & 8) != 0;
1830 down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; 1784 down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
1831 count = 1;
1832 rep = (exit_qualification & 32) != 0; 1785 rep = (exit_qualification & 32) != 0;
1833 port = exit_qualification >> 16; 1786 port = exit_qualification >> 16;
1834 address = 0; 1787
1835 if (string) { 1788 return kvm_setup_pio(vcpu, kvm_run, in, size, 1, 0, down,
1836 if (rep && !get_io_count(vcpu, &count)) 1789 0, rep, port);
1837 return 1;
1838 address = vmcs_readl(GUEST_LINEAR_ADDRESS);
1839 }
1840 return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
1841 address, rep, port);
1842} 1790}
1843 1791
1844static void 1792static void