aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Vivier <Laurent.Vivier@bull.net>2008-05-30 10:05:53 -0400
committerAvi Kivity <avi@qumranet.com>2008-07-20 05:42:30 -0400
commit92760499d01ef91518119908eb9b8798b6c9bd3f (patch)
treea6bd80fbad82589eb5aa98f81edda4537bc1f625
parent131d82791b628d4aeafd94ddc74a9b68f3d15a83 (diff)
KVM: kvm_io_device: extend in_range() to manage len and write attribute
Modify member in_range() of structure kvm_io_device to pass length and the type of the I/O (write or read). This modification allows to use kvm_io_device with coalesced MMIO. Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/ia64/kvm/kvm-ia64.c6
-rw-r--r--arch/x86/kvm/i8254.c6
-rw-r--r--arch/x86/kvm/i8259.c3
-rw-r--r--arch/x86/kvm/lapic.c3
-rw-r--r--arch/x86/kvm/x86.c28
-rw-r--r--include/linux/kvm_host.h3
-rw-r--r--virt/kvm/ioapic.c3
-rw-r--r--virt/kvm/iodev.h8
-rw-r--r--virt/kvm/kvm_main.c5
9 files changed, 40 insertions, 25 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 7c504be57972..bb58df7cc418 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -195,11 +195,11 @@ int kvm_dev_ioctl_check_extension(long ext)
195} 195}
196 196
197static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, 197static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
198 gpa_t addr) 198 gpa_t addr, int len, int is_write)
199{ 199{
200 struct kvm_io_device *dev; 200 struct kvm_io_device *dev;
201 201
202 dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr); 202 dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len, is_write);
203 203
204 return dev; 204 return dev;
205} 205}
@@ -231,7 +231,7 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
231 kvm_run->exit_reason = KVM_EXIT_MMIO; 231 kvm_run->exit_reason = KVM_EXIT_MMIO;
232 return 0; 232 return 0;
233mmio: 233mmio:
234 mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr); 234 mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr, p->size, !p->dir);
235 if (mmio_dev) { 235 if (mmio_dev) {
236 if (!p->dir) 236 if (!p->dir)
237 kvm_iodevice_write(mmio_dev, p->addr, p->size, 237 kvm_iodevice_write(mmio_dev, p->addr, p->size,
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 60074dc66bd7..9e3391e9a1b7 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -460,7 +460,8 @@ static void pit_ioport_read(struct kvm_io_device *this,
460 mutex_unlock(&pit_state->lock); 460 mutex_unlock(&pit_state->lock);
461} 461}
462 462
463static int pit_in_range(struct kvm_io_device *this, gpa_t addr) 463static int pit_in_range(struct kvm_io_device *this, gpa_t addr,
464 int len, int is_write)
464{ 465{
465 return ((addr >= KVM_PIT_BASE_ADDRESS) && 466 return ((addr >= KVM_PIT_BASE_ADDRESS) &&
466 (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); 467 (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
@@ -501,7 +502,8 @@ static void speaker_ioport_read(struct kvm_io_device *this,
501 mutex_unlock(&pit_state->lock); 502 mutex_unlock(&pit_state->lock);
502} 503}
503 504
504static int speaker_in_range(struct kvm_io_device *this, gpa_t addr) 505static int speaker_in_range(struct kvm_io_device *this, gpa_t addr,
506 int len, int is_write)
505{ 507{
506 return (addr == KVM_SPEAKER_BASE_ADDRESS); 508 return (addr == KVM_SPEAKER_BASE_ADDRESS);
507} 509}
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index ab29cf2def47..5857f59ad4aa 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -346,7 +346,8 @@ static u32 elcr_ioport_read(void *opaque, u32 addr1)
346 return s->elcr; 346 return s->elcr;
347} 347}
348 348
349static int picdev_in_range(struct kvm_io_device *this, gpa_t addr) 349static int picdev_in_range(struct kvm_io_device *this, gpa_t addr,
350 int len, int is_write)
350{ 351{
351 switch (addr) { 352 switch (addr) {
352 case 0x20: 353 case 0x20:
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index e48d19394031..180ba7316da5 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -785,7 +785,8 @@ static void apic_mmio_write(struct kvm_io_device *this,
785 785
786} 786}
787 787
788static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr) 788static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr,
789 int len, int size)
789{ 790{
790 struct kvm_lapic *apic = (struct kvm_lapic *)this->private; 791 struct kvm_lapic *apic = (struct kvm_lapic *)this->private;
791 int ret = 0; 792 int ret = 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4c94fad7f01e..ab3f5552d694 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1797,13 +1797,14 @@ static void kvm_init_msr_list(void)
1797 * Only apic need an MMIO device hook, so shortcut now.. 1797 * Only apic need an MMIO device hook, so shortcut now..
1798 */ 1798 */
1799static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu, 1799static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu,
1800 gpa_t addr) 1800 gpa_t addr, int len,
1801 int is_write)
1801{ 1802{
1802 struct kvm_io_device *dev; 1803 struct kvm_io_device *dev;
1803 1804
1804 if (vcpu->arch.apic) { 1805 if (vcpu->arch.apic) {
1805 dev = &vcpu->arch.apic->dev; 1806 dev = &vcpu->arch.apic->dev;
1806 if (dev->in_range(dev, addr)) 1807 if (dev->in_range(dev, addr, len, is_write))
1807 return dev; 1808 return dev;
1808 } 1809 }
1809 return NULL; 1810 return NULL;
@@ -1811,13 +1812,15 @@ static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu,
1811 1812
1812 1813
1813static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, 1814static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
1814 gpa_t addr) 1815 gpa_t addr, int len,
1816 int is_write)
1815{ 1817{
1816 struct kvm_io_device *dev; 1818 struct kvm_io_device *dev;
1817 1819
1818 dev = vcpu_find_pervcpu_dev(vcpu, addr); 1820 dev = vcpu_find_pervcpu_dev(vcpu, addr, len, is_write);
1819 if (dev == NULL) 1821 if (dev == NULL)
1820 dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr); 1822 dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len,
1823 is_write);
1821 return dev; 1824 return dev;
1822} 1825}
1823 1826
@@ -1885,7 +1888,7 @@ mmio:
1885 * Is this MMIO handled locally? 1888 * Is this MMIO handled locally?
1886 */ 1889 */
1887 mutex_lock(&vcpu->kvm->lock); 1890 mutex_lock(&vcpu->kvm->lock);
1888 mmio_dev = vcpu_find_mmio_dev(vcpu, gpa); 1891 mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 0);
1889 if (mmio_dev) { 1892 if (mmio_dev) {
1890 kvm_iodevice_read(mmio_dev, gpa, bytes, val); 1893 kvm_iodevice_read(mmio_dev, gpa, bytes, val);
1891 mutex_unlock(&vcpu->kvm->lock); 1894 mutex_unlock(&vcpu->kvm->lock);
@@ -1940,7 +1943,7 @@ mmio:
1940 * Is this MMIO handled locally? 1943 * Is this MMIO handled locally?
1941 */ 1944 */
1942 mutex_lock(&vcpu->kvm->lock); 1945 mutex_lock(&vcpu->kvm->lock);
1943 mmio_dev = vcpu_find_mmio_dev(vcpu, gpa); 1946 mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 1);
1944 if (mmio_dev) { 1947 if (mmio_dev) {
1945 kvm_iodevice_write(mmio_dev, gpa, bytes, val); 1948 kvm_iodevice_write(mmio_dev, gpa, bytes, val);
1946 mutex_unlock(&vcpu->kvm->lock); 1949 mutex_unlock(&vcpu->kvm->lock);
@@ -2317,9 +2320,10 @@ static void pio_string_write(struct kvm_io_device *pio_dev,
2317} 2320}
2318 2321
2319static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu, 2322static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
2320 gpa_t addr) 2323 gpa_t addr, int len,
2324 int is_write)
2321{ 2325{
2322 return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr); 2326 return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr, len, is_write);
2323} 2327}
2324 2328
2325int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, 2329int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
@@ -2351,7 +2355,7 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
2351 2355
2352 kvm_x86_ops->skip_emulated_instruction(vcpu); 2356 kvm_x86_ops->skip_emulated_instruction(vcpu);
2353 2357
2354 pio_dev = vcpu_find_pio_dev(vcpu, port); 2358 pio_dev = vcpu_find_pio_dev(vcpu, port, size, !in);
2355 if (pio_dev) { 2359 if (pio_dev) {
2356 kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data); 2360 kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data);
2357 complete_pio(vcpu); 2361 complete_pio(vcpu);
@@ -2433,7 +2437,9 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
2433 } 2437 }
2434 } 2438 }
2435 2439
2436 pio_dev = vcpu_find_pio_dev(vcpu, port); 2440 pio_dev = vcpu_find_pio_dev(vcpu, port,
2441 vcpu->arch.pio.cur_count,
2442 !vcpu->arch.pio.in);
2437 if (!vcpu->arch.pio.in) { 2443 if (!vcpu->arch.pio.in) {
2438 /* string PIO write */ 2444 /* string PIO write */
2439 ret = pio_copy_data(vcpu); 2445 ret = pio_copy_data(vcpu);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 865dcbcb891f..499ff0604234 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -52,7 +52,8 @@ struct kvm_io_bus {
52 52
53void kvm_io_bus_init(struct kvm_io_bus *bus); 53void kvm_io_bus_init(struct kvm_io_bus *bus);
54void kvm_io_bus_destroy(struct kvm_io_bus *bus); 54void kvm_io_bus_destroy(struct kvm_io_bus *bus);
55struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr); 55struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus,
56 gpa_t addr, int len, int is_write);
56void kvm_io_bus_register_dev(struct kvm_io_bus *bus, 57void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
57 struct kvm_io_device *dev); 58 struct kvm_io_device *dev);
58 59
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index d0c668c6959e..c0d22870ee9c 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -307,7 +307,8 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector)
307 __kvm_ioapic_update_eoi(ioapic, i); 307 __kvm_ioapic_update_eoi(ioapic, i);
308} 308}
309 309
310static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr) 310static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
311 int len, int is_write)
311{ 312{
312 struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private; 313 struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private;
313 314
diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h
index c14e642027b2..55e8846ac3a6 100644
--- a/virt/kvm/iodev.h
+++ b/virt/kvm/iodev.h
@@ -27,7 +27,8 @@ struct kvm_io_device {
27 gpa_t addr, 27 gpa_t addr,
28 int len, 28 int len,
29 const void *val); 29 const void *val);
30 int (*in_range)(struct kvm_io_device *this, gpa_t addr); 30 int (*in_range)(struct kvm_io_device *this, gpa_t addr, int len,
31 int is_write);
31 void (*destructor)(struct kvm_io_device *this); 32 void (*destructor)(struct kvm_io_device *this);
32 33
33 void *private; 34 void *private;
@@ -49,9 +50,10 @@ static inline void kvm_iodevice_write(struct kvm_io_device *dev,
49 dev->write(dev, addr, len, val); 50 dev->write(dev, addr, len, val);
50} 51}
51 52
52static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr) 53static inline int kvm_iodevice_inrange(struct kvm_io_device *dev,
54 gpa_t addr, int len, int is_write)
53{ 55{
54 return dev->in_range(dev, addr); 56 return dev->in_range(dev, addr, len, is_write);
55} 57}
56 58
57static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) 59static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 83a0e5ce6037..9330fad2b918 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1350,14 +1350,15 @@ void kvm_io_bus_destroy(struct kvm_io_bus *bus)
1350 } 1350 }
1351} 1351}
1352 1352
1353struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr) 1353struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus,
1354 gpa_t addr, int len, int is_write)
1354{ 1355{
1355 int i; 1356 int i;
1356 1357
1357 for (i = 0; i < bus->dev_count; i++) { 1358 for (i = 0; i < bus->dev_count; i++) {
1358 struct kvm_io_device *pos = bus->devs[i]; 1359 struct kvm_io_device *pos = bus->devs[i];
1359 1360
1360 if (pos->in_range(pos, addr)) 1361 if (pos->in_range(pos, addr, len, is_write))
1361 return pos; 1362 return pos;
1362 } 1363 }
1363 1364