diff options
author | Eddie Dong <eddie.dong@intel.com> | 2007-07-17 04:52:33 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:17 -0400 |
commit | 65619eb5a88dae3dadbb1050f957ed357aa54a50 (patch) | |
tree | 4c9d83266f84d9eed29904d2022e0625816b9fe4 | |
parent | 24cbc7e9cb0488095e4e144a762276c85ff55f9b (diff) |
KVM: In-kernel string pio write support
Add string pio write support to support some version of Windows.
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/kvm_main.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index df9c05e9b34e..1be510b657fd 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -1760,18 +1760,35 @@ static int complete_pio(struct kvm_vcpu *vcpu) | |||
1760 | return 0; | 1760 | return 0; |
1761 | } | 1761 | } |
1762 | 1762 | ||
1763 | void kernel_pio(struct kvm_io_device *pio_dev, struct kvm_vcpu *vcpu) | 1763 | static void kernel_pio(struct kvm_io_device *pio_dev, |
1764 | struct kvm_vcpu *vcpu, | ||
1765 | void *pd) | ||
1764 | { | 1766 | { |
1765 | /* TODO: String I/O for in kernel device */ | 1767 | /* TODO: String I/O for in kernel device */ |
1766 | 1768 | ||
1767 | if (vcpu->pio.in) | 1769 | if (vcpu->pio.in) |
1768 | kvm_iodevice_read(pio_dev, vcpu->pio.port, | 1770 | kvm_iodevice_read(pio_dev, vcpu->pio.port, |
1769 | vcpu->pio.size, | 1771 | vcpu->pio.size, |
1770 | vcpu->pio_data); | 1772 | pd); |
1771 | else | 1773 | else |
1772 | kvm_iodevice_write(pio_dev, vcpu->pio.port, | 1774 | kvm_iodevice_write(pio_dev, vcpu->pio.port, |
1773 | vcpu->pio.size, | 1775 | vcpu->pio.size, |
1774 | vcpu->pio_data); | 1776 | pd); |
1777 | } | ||
1778 | |||
1779 | static void pio_string_write(struct kvm_io_device *pio_dev, | ||
1780 | struct kvm_vcpu *vcpu) | ||
1781 | { | ||
1782 | struct kvm_pio_request *io = &vcpu->pio; | ||
1783 | void *pd = vcpu->pio_data; | ||
1784 | int i; | ||
1785 | |||
1786 | for (i = 0; i < io->cur_count; i++) { | ||
1787 | kvm_iodevice_write(pio_dev, io->port, | ||
1788 | io->size, | ||
1789 | pd); | ||
1790 | pd += io->size; | ||
1791 | } | ||
1775 | } | 1792 | } |
1776 | 1793 | ||
1777 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | 1794 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
@@ -1779,7 +1796,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1779 | gva_t address, int rep, unsigned port) | 1796 | gva_t address, int rep, unsigned port) |
1780 | { | 1797 | { |
1781 | unsigned now, in_page; | 1798 | unsigned now, in_page; |
1782 | int i; | 1799 | int i, ret = 0; |
1783 | int nr_pages = 1; | 1800 | int nr_pages = 1; |
1784 | struct page *page; | 1801 | struct page *page; |
1785 | struct kvm_io_device *pio_dev; | 1802 | struct kvm_io_device *pio_dev; |
@@ -1806,15 +1823,12 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1806 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); | 1823 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); |
1807 | kvm_arch_ops->decache_regs(vcpu); | 1824 | kvm_arch_ops->decache_regs(vcpu); |
1808 | if (pio_dev) { | 1825 | if (pio_dev) { |
1809 | kernel_pio(pio_dev, vcpu); | 1826 | kernel_pio(pio_dev, vcpu, vcpu->pio_data); |
1810 | complete_pio(vcpu); | 1827 | complete_pio(vcpu); |
1811 | return 1; | 1828 | return 1; |
1812 | } | 1829 | } |
1813 | return 0; | 1830 | return 0; |
1814 | } | 1831 | } |
1815 | /* TODO: String I/O for in kernel device */ | ||
1816 | if (pio_dev) | ||
1817 | printk(KERN_ERR "kvm_setup_pio: no string io support\n"); | ||
1818 | 1832 | ||
1819 | if (!count) { | 1833 | if (!count) { |
1820 | kvm_arch_ops->skip_emulated_instruction(vcpu); | 1834 | kvm_arch_ops->skip_emulated_instruction(vcpu); |
@@ -1862,9 +1876,21 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1862 | } | 1876 | } |
1863 | } | 1877 | } |
1864 | 1878 | ||
1865 | if (!vcpu->pio.in) | 1879 | if (!vcpu->pio.in) { |
1866 | return pio_copy_data(vcpu); | 1880 | /* string PIO write */ |
1867 | return 0; | 1881 | ret = pio_copy_data(vcpu); |
1882 | if (ret >= 0 && pio_dev) { | ||
1883 | pio_string_write(pio_dev, vcpu); | ||
1884 | complete_pio(vcpu); | ||
1885 | if (vcpu->pio.count == 0) | ||
1886 | ret = 1; | ||
1887 | } | ||
1888 | } else if (pio_dev) | ||
1889 | printk(KERN_ERR "no string pio read support yet, " | ||
1890 | "port %x size %d count %ld\n", | ||
1891 | port, size, count); | ||
1892 | |||
1893 | return ret; | ||
1868 | } | 1894 | } |
1869 | EXPORT_SYMBOL_GPL(kvm_setup_pio); | 1895 | EXPORT_SYMBOL_GPL(kvm_setup_pio); |
1870 | 1896 | ||