aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEddie Dong <eddie.dong@intel.com>2007-06-19 11:05:03 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-16 05:05:48 -0400
commit74906345ff9f84f2b3b772d368c7e49f4ba27456 (patch)
treec7da7fb64d076e8350233f6d0c3fb8e53a53566f /drivers
parentff1dc7942ba8fa4a86619bcb37ed68afae1f69ca (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.h5
-rw-r--r--drivers/kvm/kvm_main.c33
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
304static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) 305static 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
458struct descriptor_table { 461struct 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
1115static 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
1113static int emulator_read_emulated(unsigned long addr, 1121static 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
1843void 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
1835int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, 1857int 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);