diff options
author | Eddie Dong <eddie.dong@intel.com> | 2007-06-19 11:05:03 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-07-16 05:05:48 -0400 |
commit | 74906345ff9f84f2b3b772d368c7e49f4ba27456 (patch) | |
tree | c7da7fb64d076e8350233f6d0c3fb8e53a53566f /drivers | |
parent | ff1dc7942ba8fa4a86619bcb37ed68afae1f69ca (diff) |
KVM: Add support for in-kernel pio handlers
Useful for the PIC and PIT.
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/kvm.h | 5 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 33 |
2 files changed, 37 insertions, 1 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 31846b1c162f..a7c5e6bee034 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -241,6 +241,7 @@ struct kvm_pio_request { | |||
241 | struct page *guest_pages[2]; | 241 | struct page *guest_pages[2]; |
242 | unsigned guest_page_offset; | 242 | unsigned guest_page_offset; |
243 | int in; | 243 | int in; |
244 | int port; | ||
244 | int size; | 245 | int size; |
245 | int string; | 246 | int string; |
246 | int down; | 247 | int down; |
@@ -303,7 +304,8 @@ static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr) | |||
303 | 304 | ||
304 | static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) | 305 | static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) |
305 | { | 306 | { |
306 | dev->destructor(dev); | 307 | if (dev->destructor) |
308 | dev->destructor(dev); | ||
307 | } | 309 | } |
308 | 310 | ||
309 | /* | 311 | /* |
@@ -453,6 +455,7 @@ struct kvm { | |||
453 | struct list_head vm_list; | 455 | struct list_head vm_list; |
454 | struct file *filp; | 456 | struct file *filp; |
455 | struct kvm_io_bus mmio_bus; | 457 | struct kvm_io_bus mmio_bus; |
458 | struct kvm_io_bus pio_bus; | ||
456 | }; | 459 | }; |
457 | 460 | ||
458 | struct descriptor_table { | 461 | struct descriptor_table { |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index e157e282fcff..7826f16271e5 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -361,6 +361,7 @@ static struct kvm *kvm_create_vm(void) | |||
361 | if (!kvm) | 361 | if (!kvm) |
362 | return ERR_PTR(-ENOMEM); | 362 | return ERR_PTR(-ENOMEM); |
363 | 363 | ||
364 | kvm_io_bus_init(&kvm->pio_bus); | ||
364 | spin_lock_init(&kvm->lock); | 365 | spin_lock_init(&kvm->lock); |
365 | INIT_LIST_HEAD(&kvm->active_mmu_pages); | 366 | INIT_LIST_HEAD(&kvm->active_mmu_pages); |
366 | spin_lock(&kvm_lock); | 367 | spin_lock(&kvm_lock); |
@@ -475,6 +476,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
475 | spin_lock(&kvm_lock); | 476 | spin_lock(&kvm_lock); |
476 | list_del(&kvm->vm_list); | 477 | list_del(&kvm->vm_list); |
477 | spin_unlock(&kvm_lock); | 478 | spin_unlock(&kvm_lock); |
479 | kvm_io_bus_destroy(&kvm->pio_bus); | ||
478 | kvm_io_bus_destroy(&kvm->mmio_bus); | 480 | kvm_io_bus_destroy(&kvm->mmio_bus); |
479 | kvm_free_vcpus(kvm); | 481 | kvm_free_vcpus(kvm); |
480 | kvm_free_physmem(kvm); | 482 | kvm_free_physmem(kvm); |
@@ -1110,6 +1112,12 @@ static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, | |||
1110 | return kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr); | 1112 | return kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr); |
1111 | } | 1113 | } |
1112 | 1114 | ||
1115 | static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu, | ||
1116 | gpa_t addr) | ||
1117 | { | ||
1118 | return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr); | ||
1119 | } | ||
1120 | |||
1113 | static int emulator_read_emulated(unsigned long addr, | 1121 | static int emulator_read_emulated(unsigned long addr, |
1114 | void *val, | 1122 | void *val, |
1115 | unsigned int bytes, | 1123 | unsigned int bytes, |
@@ -1832,6 +1840,20 @@ static int complete_pio(struct kvm_vcpu *vcpu) | |||
1832 | return 0; | 1840 | return 0; |
1833 | } | 1841 | } |
1834 | 1842 | ||
1843 | void kernel_pio(struct kvm_io_device *pio_dev, struct kvm_vcpu *vcpu) | ||
1844 | { | ||
1845 | /* TODO: String I/O for in kernel device */ | ||
1846 | |||
1847 | if (vcpu->pio.in) | ||
1848 | kvm_iodevice_read(pio_dev, vcpu->pio.port, | ||
1849 | vcpu->pio.size, | ||
1850 | vcpu->pio_data); | ||
1851 | else | ||
1852 | kvm_iodevice_write(pio_dev, vcpu->pio.port, | ||
1853 | vcpu->pio.size, | ||
1854 | vcpu->pio_data); | ||
1855 | } | ||
1856 | |||
1835 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | 1857 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, |
1836 | int size, unsigned long count, int string, int down, | 1858 | int size, unsigned long count, int string, int down, |
1837 | gva_t address, int rep, unsigned port) | 1859 | gva_t address, int rep, unsigned port) |
@@ -1840,6 +1862,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1840 | int i; | 1862 | int i; |
1841 | int nr_pages = 1; | 1863 | int nr_pages = 1; |
1842 | struct page *page; | 1864 | struct page *page; |
1865 | struct kvm_io_device *pio_dev; | ||
1843 | 1866 | ||
1844 | vcpu->run->exit_reason = KVM_EXIT_IO; | 1867 | vcpu->run->exit_reason = KVM_EXIT_IO; |
1845 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | 1868 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; |
@@ -1851,17 +1874,27 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | |||
1851 | vcpu->pio.cur_count = count; | 1874 | vcpu->pio.cur_count = count; |
1852 | vcpu->pio.size = size; | 1875 | vcpu->pio.size = size; |
1853 | vcpu->pio.in = in; | 1876 | vcpu->pio.in = in; |
1877 | vcpu->pio.port = port; | ||
1854 | vcpu->pio.string = string; | 1878 | vcpu->pio.string = string; |
1855 | vcpu->pio.down = down; | 1879 | vcpu->pio.down = down; |
1856 | vcpu->pio.guest_page_offset = offset_in_page(address); | 1880 | vcpu->pio.guest_page_offset = offset_in_page(address); |
1857 | vcpu->pio.rep = rep; | 1881 | vcpu->pio.rep = rep; |
1858 | 1882 | ||
1883 | pio_dev = vcpu_find_pio_dev(vcpu, port); | ||
1859 | if (!string) { | 1884 | if (!string) { |
1860 | kvm_arch_ops->cache_regs(vcpu); | 1885 | kvm_arch_ops->cache_regs(vcpu); |
1861 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); | 1886 | memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4); |
1862 | kvm_arch_ops->decache_regs(vcpu); | 1887 | kvm_arch_ops->decache_regs(vcpu); |
1888 | if (pio_dev) { | ||
1889 | kernel_pio(pio_dev, vcpu); | ||
1890 | complete_pio(vcpu); | ||
1891 | return 1; | ||
1892 | } | ||
1863 | return 0; | 1893 | return 0; |
1864 | } | 1894 | } |
1895 | /* TODO: String I/O for in kernel device */ | ||
1896 | if (pio_dev) | ||
1897 | printk(KERN_ERR "kvm_setup_pio: no string io support\n"); | ||
1865 | 1898 | ||
1866 | if (!count) { | 1899 | if (!count) { |
1867 | kvm_arch_ops->skip_emulated_instruction(vcpu); | 1900 | kvm_arch_ops->skip_emulated_instruction(vcpu); |