diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/kvm.h | 8 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 63 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 3 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 3 | ||||
-rw-r--r-- | drivers/kvm/x86_emulate.c | 6 |
5 files changed, 48 insertions, 35 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 6d258261891e..2245baeeb022 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -539,9 +539,11 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); | |||
539 | 539 | ||
540 | struct x86_emulate_ctxt; | 540 | struct x86_emulate_ctxt; |
541 | 541 | ||
542 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | 542 | int kvm_emulate_pio (struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
543 | int size, unsigned long count, int string, int down, | 543 | int size, unsigned port); |
544 | gva_t address, int rep, unsigned port); | 544 | int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
545 | int size, unsigned long count, int down, | ||
546 | gva_t address, int rep, unsigned port); | ||
545 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu); | 547 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu); |
546 | int kvm_emulate_halt(struct kvm_vcpu *vcpu); | 548 | int kvm_emulate_halt(struct kvm_vcpu *vcpu); |
547 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); | 549 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 661d065fd866..d154487b7729 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -1735,8 +1735,39 @@ static void pio_string_write(struct kvm_io_device *pio_dev, | |||
1735 | } | 1735 | } |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | 1738 | int kvm_emulate_pio (struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
1739 | int size, unsigned long count, int string, int down, | 1739 | int size, unsigned port) |
1740 | { | ||
1741 | struct kvm_io_device *pio_dev; | ||
1742 | |||
1743 | vcpu->run->exit_reason = KVM_EXIT_IO; | ||
1744 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | ||
1745 | vcpu->run->io.size = vcpu->pio.size = size; | ||
1746 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | ||
1747 | vcpu->run->io.count = vcpu->pio.count = vcpu->pio.cur_count = 1; | ||
1748 | vcpu->run->io.port = vcpu->pio.port = port; | ||
1749 | vcpu->pio.in = in; | ||
1750 | vcpu->pio.string = 0; | ||
1751 | vcpu->pio.down = 0; | ||
1752 | vcpu->pio.guest_page_offset = 0; | ||
1753 | vcpu->pio.rep = 0; | ||
1754 | |||
1755 | kvm_arch_ops->cache_regs(vcpu); | ||
1756 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); | ||
1757 | kvm_arch_ops->decache_regs(vcpu); | ||
1758 | |||
1759 | pio_dev = vcpu_find_pio_dev(vcpu, port); | ||
1760 | if (pio_dev) { | ||
1761 | kernel_pio(pio_dev, vcpu, vcpu->pio_data); | ||
1762 | complete_pio(vcpu); | ||
1763 | return 1; | ||
1764 | } | ||
1765 | return 0; | ||
1766 | } | ||
1767 | EXPORT_SYMBOL_GPL(kvm_emulate_pio); | ||
1768 | |||
1769 | int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | ||
1770 | int size, unsigned long count, int down, | ||
1740 | gva_t address, int rep, unsigned port) | 1771 | gva_t address, int rep, unsigned port) |
1741 | { | 1772 | { |
1742 | unsigned now, in_page; | 1773 | unsigned now, in_page; |
@@ -1747,33 +1778,16 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1747 | 1778 | ||
1748 | vcpu->run->exit_reason = KVM_EXIT_IO; | 1779 | vcpu->run->exit_reason = KVM_EXIT_IO; |
1749 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | 1780 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; |
1750 | vcpu->run->io.size = size; | 1781 | vcpu->run->io.size = vcpu->pio.size = size; |
1751 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | 1782 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; |
1752 | vcpu->run->io.count = count; | 1783 | vcpu->run->io.count = vcpu->pio.count = vcpu->pio.cur_count = count; |
1753 | vcpu->run->io.port = port; | 1784 | vcpu->run->io.port = vcpu->pio.port = port; |
1754 | vcpu->pio.count = count; | ||
1755 | vcpu->pio.cur_count = count; | ||
1756 | vcpu->pio.size = size; | ||
1757 | vcpu->pio.in = in; | 1785 | vcpu->pio.in = in; |
1758 | vcpu->pio.port = port; | 1786 | vcpu->pio.string = 1; |
1759 | vcpu->pio.string = string; | ||
1760 | vcpu->pio.down = down; | 1787 | vcpu->pio.down = down; |
1761 | vcpu->pio.guest_page_offset = offset_in_page(address); | 1788 | vcpu->pio.guest_page_offset = offset_in_page(address); |
1762 | vcpu->pio.rep = rep; | 1789 | vcpu->pio.rep = rep; |
1763 | 1790 | ||
1764 | pio_dev = vcpu_find_pio_dev(vcpu, port); | ||
1765 | if (!string) { | ||
1766 | kvm_arch_ops->cache_regs(vcpu); | ||
1767 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); | ||
1768 | kvm_arch_ops->decache_regs(vcpu); | ||
1769 | if (pio_dev) { | ||
1770 | kernel_pio(pio_dev, vcpu, vcpu->pio_data); | ||
1771 | complete_pio(vcpu); | ||
1772 | return 1; | ||
1773 | } | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | if (!count) { | 1791 | if (!count) { |
1778 | kvm_arch_ops->skip_emulated_instruction(vcpu); | 1792 | kvm_arch_ops->skip_emulated_instruction(vcpu); |
1779 | return 1; | 1793 | return 1; |
@@ -1818,6 +1832,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1818 | } | 1832 | } |
1819 | } | 1833 | } |
1820 | 1834 | ||
1835 | pio_dev = vcpu_find_pio_dev(vcpu, port); | ||
1821 | if (!vcpu->pio.in) { | 1836 | if (!vcpu->pio.in) { |
1822 | /* string PIO write */ | 1837 | /* string PIO write */ |
1823 | ret = pio_copy_data(vcpu); | 1838 | ret = pio_copy_data(vcpu); |
@@ -1834,7 +1849,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1834 | 1849 | ||
1835 | return ret; | 1850 | return ret; |
1836 | } | 1851 | } |
1837 | EXPORT_SYMBOL_GPL(kvm_setup_pio); | 1852 | EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); |
1838 | 1853 | ||
1839 | static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1854 | static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
1840 | { | 1855 | { |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index a83ff01bb014..e3c6d891326b 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -1005,8 +1005,7 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | |||
1005 | rep = (io_info & SVM_IOIO_REP_MASK) != 0; | 1005 | rep = (io_info & SVM_IOIO_REP_MASK) != 0; |
1006 | down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0; | 1006 | down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0; |
1007 | 1007 | ||
1008 | return kvm_setup_pio(&svm->vcpu, kvm_run, in, size, 1, 0, | 1008 | return kvm_emulate_pio(&svm->vcpu, kvm_run, in, size, port); |
1009 | down, 0, rep, port); | ||
1010 | } | 1009 | } |
1011 | 1010 | ||
1012 | static int nop_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | 1011 | static int nop_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 044722bc1a7f..906d4fa13d10 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1785,8 +1785,7 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1785 | rep = (exit_qualification & 32) != 0; | 1785 | rep = (exit_qualification & 32) != 0; |
1786 | port = exit_qualification >> 16; | 1786 | port = exit_qualification >> 16; |
1787 | 1787 | ||
1788 | return kvm_setup_pio(vcpu, kvm_run, in, size, 1, 0, down, | 1788 | return kvm_emulate_pio(vcpu, kvm_run, in, size, port); |
1789 | 0, rep, port); | ||
1790 | } | 1789 | } |
1791 | 1790 | ||
1792 | static void | 1791 | static void |
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index d553719fc4cb..b4f439cfc66e 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -1123,12 +1123,11 @@ special_insn: | |||
1123 | switch(b) { | 1123 | switch(b) { |
1124 | case 0x6c: /* insb */ | 1124 | case 0x6c: /* insb */ |
1125 | case 0x6d: /* insw/insd */ | 1125 | case 0x6d: /* insw/insd */ |
1126 | if (kvm_setup_pio(ctxt->vcpu, NULL, | 1126 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, |
1127 | 1, /* in */ | 1127 | 1, /* in */ |
1128 | (d & ByteOp) ? 1 : op_bytes, /* size */ | 1128 | (d & ByteOp) ? 1 : op_bytes, /* size */ |
1129 | rep_prefix ? | 1129 | rep_prefix ? |
1130 | address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ | 1130 | address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ |
1131 | 1, /* strings */ | ||
1132 | (_eflags & EFLG_DF), /* down */ | 1131 | (_eflags & EFLG_DF), /* down */ |
1133 | register_address(ctxt->es_base, | 1132 | register_address(ctxt->es_base, |
1134 | _regs[VCPU_REGS_RDI]), /* address */ | 1133 | _regs[VCPU_REGS_RDI]), /* address */ |
@@ -1139,12 +1138,11 @@ special_insn: | |||
1139 | return 0; | 1138 | return 0; |
1140 | case 0x6e: /* outsb */ | 1139 | case 0x6e: /* outsb */ |
1141 | case 0x6f: /* outsw/outsd */ | 1140 | case 0x6f: /* outsw/outsd */ |
1142 | if (kvm_setup_pio(ctxt->vcpu, NULL, | 1141 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, |
1143 | 0, /* in */ | 1142 | 0, /* in */ |
1144 | (d & ByteOp) ? 1 : op_bytes, /* size */ | 1143 | (d & ByteOp) ? 1 : op_bytes, /* size */ |
1145 | rep_prefix ? | 1144 | rep_prefix ? |
1146 | address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ | 1145 | address_mask(_regs[VCPU_REGS_RCX]) : 1, /* count */ |
1147 | 1, /* strings */ | ||
1148 | (_eflags & EFLG_DF), /* down */ | 1146 | (_eflags & EFLG_DF), /* down */ |
1149 | register_address(override_base ? | 1147 | register_address(override_base ? |
1150 | *override_base : ctxt->ds_base, | 1148 | *override_base : ctxt->ds_base, |