diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2009-06-29 15:24:32 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:33:05 -0400 |
commit | bda9020e2463ec94db9f97e8615f3bae22069838 (patch) | |
tree | 48125316d4c0f419a35aefdfbf665d30ad0c55ca /arch/x86/kvm/i8254.c | |
parent | 6c474694530f377507f9aca438c17206e051e6e7 (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/i8254.c')
-rw-r--r-- | arch/x86/kvm/i8254.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 4082cdd468ed..8c3ac30ef9bd 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -358,8 +358,14 @@ static inline struct kvm_pit *speaker_to_pit(struct kvm_io_device *dev) | |||
358 | return container_of(dev, struct kvm_pit, speaker_dev); | 358 | return container_of(dev, struct kvm_pit, speaker_dev); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void pit_ioport_write(struct kvm_io_device *this, | 361 | static inline int pit_in_range(gpa_t addr) |
362 | gpa_t addr, int len, const void *data) | 362 | { |
363 | return ((addr >= KVM_PIT_BASE_ADDRESS) && | ||
364 | (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); | ||
365 | } | ||
366 | |||
367 | static int pit_ioport_write(struct kvm_io_device *this, | ||
368 | gpa_t addr, int len, const void *data) | ||
363 | { | 369 | { |
364 | struct kvm_pit *pit = dev_to_pit(this); | 370 | struct kvm_pit *pit = dev_to_pit(this); |
365 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 371 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
@@ -367,6 +373,8 @@ static void pit_ioport_write(struct kvm_io_device *this, | |||
367 | int channel, access; | 373 | int channel, access; |
368 | struct kvm_kpit_channel_state *s; | 374 | struct kvm_kpit_channel_state *s; |
369 | u32 val = *(u32 *) data; | 375 | u32 val = *(u32 *) data; |
376 | if (!pit_in_range(addr)) | ||
377 | return -EOPNOTSUPP; | ||
370 | 378 | ||
371 | val &= 0xff; | 379 | val &= 0xff; |
372 | addr &= KVM_PIT_CHANNEL_MASK; | 380 | addr &= KVM_PIT_CHANNEL_MASK; |
@@ -429,16 +437,19 @@ static void pit_ioport_write(struct kvm_io_device *this, | |||
429 | } | 437 | } |
430 | 438 | ||
431 | mutex_unlock(&pit_state->lock); | 439 | mutex_unlock(&pit_state->lock); |
440 | return 0; | ||
432 | } | 441 | } |
433 | 442 | ||
434 | static void pit_ioport_read(struct kvm_io_device *this, | 443 | static int pit_ioport_read(struct kvm_io_device *this, |
435 | gpa_t addr, int len, void *data) | 444 | gpa_t addr, int len, void *data) |
436 | { | 445 | { |
437 | struct kvm_pit *pit = dev_to_pit(this); | 446 | struct kvm_pit *pit = dev_to_pit(this); |
438 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 447 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
439 | struct kvm *kvm = pit->kvm; | 448 | struct kvm *kvm = pit->kvm; |
440 | int ret, count; | 449 | int ret, count; |
441 | struct kvm_kpit_channel_state *s; | 450 | struct kvm_kpit_channel_state *s; |
451 | if (!pit_in_range(addr)) | ||
452 | return -EOPNOTSUPP; | ||
442 | 453 | ||
443 | addr &= KVM_PIT_CHANNEL_MASK; | 454 | addr &= KVM_PIT_CHANNEL_MASK; |
444 | s = &pit_state->channels[addr]; | 455 | s = &pit_state->channels[addr]; |
@@ -493,37 +504,36 @@ static void pit_ioport_read(struct kvm_io_device *this, | |||
493 | memcpy(data, (char *)&ret, len); | 504 | memcpy(data, (char *)&ret, len); |
494 | 505 | ||
495 | mutex_unlock(&pit_state->lock); | 506 | mutex_unlock(&pit_state->lock); |
507 | return 0; | ||
496 | } | 508 | } |
497 | 509 | ||
498 | static int pit_in_range(struct kvm_io_device *this, gpa_t addr, | 510 | static int speaker_ioport_write(struct kvm_io_device *this, |
499 | int len, int is_write) | 511 | gpa_t addr, int len, const void *data) |
500 | { | ||
501 | return ((addr >= KVM_PIT_BASE_ADDRESS) && | ||
502 | (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); | ||
503 | } | ||
504 | |||
505 | static void speaker_ioport_write(struct kvm_io_device *this, | ||
506 | gpa_t addr, int len, const void *data) | ||
507 | { | 512 | { |
508 | struct kvm_pit *pit = speaker_to_pit(this); | 513 | struct kvm_pit *pit = speaker_to_pit(this); |
509 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 514 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
510 | struct kvm *kvm = pit->kvm; | 515 | struct kvm *kvm = pit->kvm; |
511 | u32 val = *(u32 *) data; | 516 | u32 val = *(u32 *) data; |
517 | if (addr != KVM_SPEAKER_BASE_ADDRESS) | ||
518 | return -EOPNOTSUPP; | ||
512 | 519 | ||
513 | mutex_lock(&pit_state->lock); | 520 | mutex_lock(&pit_state->lock); |
514 | pit_state->speaker_data_on = (val >> 1) & 1; | 521 | pit_state->speaker_data_on = (val >> 1) & 1; |
515 | pit_set_gate(kvm, 2, val & 1); | 522 | pit_set_gate(kvm, 2, val & 1); |
516 | mutex_unlock(&pit_state->lock); | 523 | mutex_unlock(&pit_state->lock); |
524 | return 0; | ||
517 | } | 525 | } |
518 | 526 | ||
519 | static void speaker_ioport_read(struct kvm_io_device *this, | 527 | static int speaker_ioport_read(struct kvm_io_device *this, |
520 | gpa_t addr, int len, void *data) | 528 | gpa_t addr, int len, void *data) |
521 | { | 529 | { |
522 | struct kvm_pit *pit = speaker_to_pit(this); | 530 | struct kvm_pit *pit = speaker_to_pit(this); |
523 | struct kvm_kpit_state *pit_state = &pit->pit_state; | 531 | struct kvm_kpit_state *pit_state = &pit->pit_state; |
524 | struct kvm *kvm = pit->kvm; | 532 | struct kvm *kvm = pit->kvm; |
525 | unsigned int refresh_clock; | 533 | unsigned int refresh_clock; |
526 | int ret; | 534 | int ret; |
535 | if (addr != KVM_SPEAKER_BASE_ADDRESS) | ||
536 | return -EOPNOTSUPP; | ||
527 | 537 | ||
528 | /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ | 538 | /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ |
529 | refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1; | 539 | refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1; |
@@ -535,12 +545,7 @@ static void speaker_ioport_read(struct kvm_io_device *this, | |||
535 | len = sizeof(ret); | 545 | len = sizeof(ret); |
536 | memcpy(data, (char *)&ret, len); | 546 | memcpy(data, (char *)&ret, len); |
537 | mutex_unlock(&pit_state->lock); | 547 | mutex_unlock(&pit_state->lock); |
538 | } | 548 | return 0; |
539 | |||
540 | static int speaker_in_range(struct kvm_io_device *this, gpa_t addr, | ||
541 | int len, int is_write) | ||
542 | { | ||
543 | return (addr == KVM_SPEAKER_BASE_ADDRESS); | ||
544 | } | 549 | } |
545 | 550 | ||
546 | void kvm_pit_reset(struct kvm_pit *pit) | 551 | void kvm_pit_reset(struct kvm_pit *pit) |
@@ -574,13 +579,11 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) | |||
574 | static const struct kvm_io_device_ops pit_dev_ops = { | 579 | static const struct kvm_io_device_ops pit_dev_ops = { |
575 | .read = pit_ioport_read, | 580 | .read = pit_ioport_read, |
576 | .write = pit_ioport_write, | 581 | .write = pit_ioport_write, |
577 | .in_range = pit_in_range, | ||
578 | }; | 582 | }; |
579 | 583 | ||
580 | static const struct kvm_io_device_ops speaker_dev_ops = { | 584 | static const struct kvm_io_device_ops speaker_dev_ops = { |
581 | .read = speaker_ioport_read, | 585 | .read = speaker_ioport_read, |
582 | .write = speaker_ioport_write, | 586 | .write = speaker_ioport_write, |
583 | .in_range = speaker_in_range, | ||
584 | }; | 587 | }; |
585 | 588 | ||
586 | /* Caller must have writers lock on slots_lock */ | 589 | /* Caller must have writers lock on slots_lock */ |