aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/i8259.c
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 /arch/x86/kvm/i8259.c
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 'arch/x86/kvm/i8259.c')
-rw-r--r--arch/x86/kvm/i8259.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 1851aec8a7da..1d1bb75dc7bc 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -430,8 +430,7 @@ static u32 elcr_ioport_read(void *opaque, u32 addr1)
430 return s->elcr; 430 return s->elcr;
431} 431}
432 432
433static int picdev_in_range(struct kvm_io_device *this, gpa_t addr, 433static int picdev_in_range(gpa_t addr)
434 int len, int is_write)
435{ 434{
436 switch (addr) { 435 switch (addr) {
437 case 0x20: 436 case 0x20:
@@ -451,16 +450,18 @@ static inline struct kvm_pic *to_pic(struct kvm_io_device *dev)
451 return container_of(dev, struct kvm_pic, dev); 450 return container_of(dev, struct kvm_pic, dev);
452} 451}
453 452
454static void picdev_write(struct kvm_io_device *this, 453static int picdev_write(struct kvm_io_device *this,
455 gpa_t addr, int len, const void *val) 454 gpa_t addr, int len, const void *val)
456{ 455{
457 struct kvm_pic *s = to_pic(this); 456 struct kvm_pic *s = to_pic(this);
458 unsigned char data = *(unsigned char *)val; 457 unsigned char data = *(unsigned char *)val;
458 if (!picdev_in_range(addr))
459 return -EOPNOTSUPP;
459 460
460 if (len != 1) { 461 if (len != 1) {
461 if (printk_ratelimit()) 462 if (printk_ratelimit())
462 printk(KERN_ERR "PIC: non byte write\n"); 463 printk(KERN_ERR "PIC: non byte write\n");
463 return; 464 return 0;
464 } 465 }
465 pic_lock(s); 466 pic_lock(s);
466 switch (addr) { 467 switch (addr) {
@@ -476,18 +477,21 @@ static void picdev_write(struct kvm_io_device *this,
476 break; 477 break;
477 } 478 }
478 pic_unlock(s); 479 pic_unlock(s);
480 return 0;
479} 481}
480 482
481static void picdev_read(struct kvm_io_device *this, 483static int picdev_read(struct kvm_io_device *this,
482 gpa_t addr, int len, void *val) 484 gpa_t addr, int len, void *val)
483{ 485{
484 struct kvm_pic *s = to_pic(this); 486 struct kvm_pic *s = to_pic(this);
485 unsigned char data = 0; 487 unsigned char data = 0;
488 if (!picdev_in_range(addr))
489 return -EOPNOTSUPP;
486 490
487 if (len != 1) { 491 if (len != 1) {
488 if (printk_ratelimit()) 492 if (printk_ratelimit())
489 printk(KERN_ERR "PIC: non byte read\n"); 493 printk(KERN_ERR "PIC: non byte read\n");
490 return; 494 return 0;
491 } 495 }
492 pic_lock(s); 496 pic_lock(s);
493 switch (addr) { 497 switch (addr) {
@@ -504,6 +508,7 @@ static void picdev_read(struct kvm_io_device *this,
504 } 508 }
505 *(unsigned char *)val = data; 509 *(unsigned char *)val = data;
506 pic_unlock(s); 510 pic_unlock(s);
511 return 0;
507} 512}
508 513
509/* 514/*
@@ -526,7 +531,6 @@ static void pic_irq_request(void *opaque, int level)
526static const struct kvm_io_device_ops picdev_ops = { 531static const struct kvm_io_device_ops picdev_ops = {
527 .read = picdev_read, 532 .read = picdev_read,
528 .write = picdev_write, 533 .write = picdev_write,
529 .in_range = picdev_in_range,
530}; 534};
531 535
532struct kvm_pic *kvm_create_pic(struct kvm *kvm) 536struct kvm_pic *kvm_create_pic(struct kvm *kvm)