aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2009-06-29 15:24:32 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:33:05 -0400
commitbda9020e2463ec94db9f97e8615f3bae22069838 (patch)
tree48125316d4c0f419a35aefdfbf665d30ad0c55ca /virt
parent6c474694530f377507f9aca438c17206e051e6e7 (diff)
KVM: remove in_range from io devices
This changes bus accesses to use high-level kvm_io_bus_read/kvm_io_bus_write functions. in_range now becomes unused so it is removed from device ops in favor of read/write callbacks performing range checks internally. This allows aliasing (mostly for in-kernel virtio), as well as better error handling by making it possible to pass errors up to userspace. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/coalesced_mmio.c16
-rw-r--r--virt/kvm/ioapic.c22
-rw-r--r--virt/kvm/iodev.h39
-rw-r--r--virt/kvm/kvm_main.c26
4 files changed, 50 insertions, 53 deletions
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 7b7cc9fe5ee3..0352f81ecc0b 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -19,18 +19,14 @@ static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev)
19 return container_of(dev, struct kvm_coalesced_mmio_dev, dev); 19 return container_of(dev, struct kvm_coalesced_mmio_dev, dev);
20} 20}
21 21
22static int coalesced_mmio_in_range(struct kvm_io_device *this, 22static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev,
23 gpa_t addr, int len, int is_write) 23 gpa_t addr, int len)
24{ 24{
25 struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
26 struct kvm_coalesced_mmio_zone *zone; 25 struct kvm_coalesced_mmio_zone *zone;
27 struct kvm_coalesced_mmio_ring *ring; 26 struct kvm_coalesced_mmio_ring *ring;
28 unsigned avail; 27 unsigned avail;
29 int i; 28 int i;
30 29
31 if (!is_write)
32 return 0;
33
34 /* Are we able to batch it ? */ 30 /* Are we able to batch it ? */
35 31
36 /* last is the first free entry 32 /* last is the first free entry
@@ -60,11 +56,13 @@ static int coalesced_mmio_in_range(struct kvm_io_device *this,
60 return 0; 56 return 0;
61} 57}
62 58
63static void coalesced_mmio_write(struct kvm_io_device *this, 59static int coalesced_mmio_write(struct kvm_io_device *this,
64 gpa_t addr, int len, const void *val) 60 gpa_t addr, int len, const void *val)
65{ 61{
66 struct kvm_coalesced_mmio_dev *dev = to_mmio(this); 62 struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
67 struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; 63 struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
64 if (!coalesced_mmio_in_range(dev, addr, len))
65 return -EOPNOTSUPP;
68 66
69 spin_lock(&dev->lock); 67 spin_lock(&dev->lock);
70 68
@@ -76,6 +74,7 @@ static void coalesced_mmio_write(struct kvm_io_device *this,
76 smp_wmb(); 74 smp_wmb();
77 ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; 75 ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX;
78 spin_unlock(&dev->lock); 76 spin_unlock(&dev->lock);
77 return 0;
79} 78}
80 79
81static void coalesced_mmio_destructor(struct kvm_io_device *this) 80static void coalesced_mmio_destructor(struct kvm_io_device *this)
@@ -87,7 +86,6 @@ static void coalesced_mmio_destructor(struct kvm_io_device *this)
87 86
88static const struct kvm_io_device_ops coalesced_mmio_ops = { 87static const struct kvm_io_device_ops coalesced_mmio_ops = {
89 .write = coalesced_mmio_write, 88 .write = coalesced_mmio_write,
90 .in_range = coalesced_mmio_in_range,
91 .destructor = coalesced_mmio_destructor, 89 .destructor = coalesced_mmio_destructor,
92}; 90};
93 91
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 0eca54e06326..ddf6aa998b18 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -227,20 +227,19 @@ static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev)
227 return container_of(dev, struct kvm_ioapic, dev); 227 return container_of(dev, struct kvm_ioapic, dev);
228} 228}
229 229
230static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr, 230static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr)
231 int len, int is_write)
232{ 231{
233 struct kvm_ioapic *ioapic = to_ioapic(this);
234
235 return ((addr >= ioapic->base_address && 232 return ((addr >= ioapic->base_address &&
236 (addr < ioapic->base_address + IOAPIC_MEM_LENGTH))); 233 (addr < ioapic->base_address + IOAPIC_MEM_LENGTH)));
237} 234}
238 235
239static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, 236static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,
240 void *val) 237 void *val)
241{ 238{
242 struct kvm_ioapic *ioapic = to_ioapic(this); 239 struct kvm_ioapic *ioapic = to_ioapic(this);
243 u32 result; 240 u32 result;
241 if (!ioapic_in_range(ioapic, addr))
242 return -EOPNOTSUPP;
244 243
245 ioapic_debug("addr %lx\n", (unsigned long)addr); 244 ioapic_debug("addr %lx\n", (unsigned long)addr);
246 ASSERT(!(addr & 0xf)); /* check alignment */ 245 ASSERT(!(addr & 0xf)); /* check alignment */
@@ -273,13 +272,16 @@ static void ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,
273 printk(KERN_WARNING "ioapic: wrong length %d\n", len); 272 printk(KERN_WARNING "ioapic: wrong length %d\n", len);
274 } 273 }
275 mutex_unlock(&ioapic->kvm->irq_lock); 274 mutex_unlock(&ioapic->kvm->irq_lock);
275 return 0;
276} 276}
277 277
278static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, 278static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
279 const void *val) 279 const void *val)
280{ 280{
281 struct kvm_ioapic *ioapic = to_ioapic(this); 281 struct kvm_ioapic *ioapic = to_ioapic(this);
282 u32 data; 282 u32 data;
283 if (!ioapic_in_range(ioapic, addr))
284 return -EOPNOTSUPP;
283 285
284 ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n", 286 ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n",
285 (void*)addr, len, val); 287 (void*)addr, len, val);
@@ -290,7 +292,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
290 data = *(u32 *) val; 292 data = *(u32 *) val;
291 else { 293 else {
292 printk(KERN_WARNING "ioapic: Unsupported size %d\n", len); 294 printk(KERN_WARNING "ioapic: Unsupported size %d\n", len);
293 return; 295 return 0;
294 } 296 }
295 297
296 addr &= 0xff; 298 addr &= 0xff;
@@ -312,6 +314,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
312 break; 314 break;
313 } 315 }
314 mutex_unlock(&ioapic->kvm->irq_lock); 316 mutex_unlock(&ioapic->kvm->irq_lock);
317 return 0;
315} 318}
316 319
317void kvm_ioapic_reset(struct kvm_ioapic *ioapic) 320void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
@@ -329,7 +332,6 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
329static const struct kvm_io_device_ops ioapic_mmio_ops = { 332static const struct kvm_io_device_ops ioapic_mmio_ops = {
330 .read = ioapic_mmio_read, 333 .read = ioapic_mmio_read,
331 .write = ioapic_mmio_write, 334 .write = ioapic_mmio_write,
332 .in_range = ioapic_in_range,
333}; 335};
334 336
335int kvm_ioapic_init(struct kvm *kvm) 337int kvm_ioapic_init(struct kvm *kvm)
diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h
index 06e38b23fa61..12fd3caffd2b 100644
--- a/virt/kvm/iodev.h
+++ b/virt/kvm/iodev.h
@@ -17,23 +17,24 @@
17#define __KVM_IODEV_H__ 17#define __KVM_IODEV_H__
18 18
19#include <linux/kvm_types.h> 19#include <linux/kvm_types.h>
20#include <asm/errno.h>
20 21
21struct kvm_io_device; 22struct kvm_io_device;
22 23
23/** 24/**
24 * kvm_io_device_ops are called under kvm slots_lock. 25 * kvm_io_device_ops are called under kvm slots_lock.
26 * read and write handlers return 0 if the transaction has been handled,
27 * or non-zero to have it passed to the next device.
25 **/ 28 **/
26struct kvm_io_device_ops { 29struct kvm_io_device_ops {
27 void (*read)(struct kvm_io_device *this, 30 int (*read)(struct kvm_io_device *this,
31 gpa_t addr,
32 int len,
33 void *val);
34 int (*write)(struct kvm_io_device *this,
28 gpa_t addr, 35 gpa_t addr,
29 int len, 36 int len,
30 void *val); 37 const void *val);
31 void (*write)(struct kvm_io_device *this,
32 gpa_t addr,
33 int len,
34 const void *val);
35 int (*in_range)(struct kvm_io_device *this, gpa_t addr, int len,
36 int is_write);
37 void (*destructor)(struct kvm_io_device *this); 38 void (*destructor)(struct kvm_io_device *this);
38}; 39};
39 40
@@ -48,26 +49,16 @@ static inline void kvm_iodevice_init(struct kvm_io_device *dev,
48 dev->ops = ops; 49 dev->ops = ops;
49} 50}
50 51
51static inline void kvm_iodevice_read(struct kvm_io_device *dev, 52static inline int kvm_iodevice_read(struct kvm_io_device *dev,
52 gpa_t addr, 53 gpa_t addr, int l, void *v)
53 int len,
54 void *val)
55{ 54{
56 dev->ops->read(dev, addr, len, val); 55 return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP;
57} 56}
58 57
59static inline void kvm_iodevice_write(struct kvm_io_device *dev, 58static inline int kvm_iodevice_write(struct kvm_io_device *dev,
60 gpa_t addr, 59 gpa_t addr, int l, const void *v)
61 int len,
62 const void *val)
63{ 60{
64 dev->ops->write(dev, addr, len, val); 61 return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP;
65}
66
67static inline int kvm_iodevice_in_range(struct kvm_io_device *dev,
68 gpa_t addr, int len, int is_write)
69{
70 return dev->ops->in_range(dev, addr, len, is_write);
71} 62}
72 63
73static inline void kvm_iodevice_destructor(struct kvm_io_device *dev) 64static 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 0edc366ecf89..594606526620 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2512,19 +2512,25 @@ void kvm_io_bus_destroy(struct kvm_io_bus *bus)
2512 } 2512 }
2513} 2513}
2514 2514
2515struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, 2515/* kvm_io_bus_write - called under kvm->slots_lock */
2516 gpa_t addr, int len, int is_write) 2516int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr,
2517 int len, const void *val)
2517{ 2518{
2518 int i; 2519 int i;
2520 for (i = 0; i < bus->dev_count; i++)
2521 if (!kvm_iodevice_write(bus->devs[i], addr, len, val))
2522 return 0;
2523 return -EOPNOTSUPP;
2524}
2519 2525
2520 for (i = 0; i < bus->dev_count; i++) { 2526/* kvm_io_bus_read - called under kvm->slots_lock */
2521 struct kvm_io_device *pos = bus->devs[i]; 2527int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val)
2522 2528{
2523 if (kvm_iodevice_in_range(pos, addr, len, is_write)) 2529 int i;
2524 return pos; 2530 for (i = 0; i < bus->dev_count; i++)
2525 } 2531 if (!kvm_iodevice_read(bus->devs[i], addr, len, val))
2526 2532 return 0;
2527 return NULL; 2533 return -EOPNOTSUPP;
2528} 2534}
2529 2535
2530void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, 2536void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,