Add a very simple allocation of ioports. This prevents the need to coordinate ioports between different modules. Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/include/kvm/ioport.h | 11 +++++++++-- tools/kvm/ioport.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h index 2a8d74d..c500f1e 100644 --- a/tools/kvm/include/kvm/ioport.h +++ b/tools/kvm/include/kvm/ioport.h @@ -7,6 +7,9 @@ /* some ports we reserve for own use */ #define IOPORT_DBG 0xe0 +#define IOPORT_START 0x6200 +#define IOPORT_SIZE 0x400 + #define IOPORT_VESA 0xa200 #define IOPORT_VESA_SIZE 256 #define IOPORT_VIRTIO_P9 0xb200 /* Virtio 9P device */ @@ -20,6 +23,8 @@ #define IOPORT_VIRTIO_RNG 0xf200 /* Virtio network device */ #define IOPORT_VIRTIO_RNG_SIZE 256 +#define IOPORT_EMPTY USHRT_MAX + struct kvm; struct ioport_operations { @@ -31,8 +36,10 @@ struct ioport_operations { void ioport__setup_legacy(void); -void ioport__register(u16 port, struct ioport_operations *ops, int count); -void ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param); +u16 ioport__register(u16 port, struct ioport_operations *ops, int count); +u16 ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param); + +u16 ioport__find_free_range(void); static inline u8 ioport__read8(u8 *data) { diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c index 159d089..b2a3272 100644 --- a/tools/kvm/ioport.c +++ b/tools/kvm/ioport.c @@ -3,6 +3,7 @@ #include "kvm/kvm.h" #include "kvm/util.h" #include "kvm/rbtree-interval.h" +#include "kvm/mutex.h" #include <linux/kvm.h> /* for KVM_EXIT_* */ #include <linux/types.h> @@ -21,9 +22,23 @@ struct ioport_entry { void *param; }; +static u16 free_io_port_idx; +DEFINE_MUTEX(free_io_port_idx_lock); static struct rb_root ioport_tree = RB_ROOT; bool ioport_debug; +static u16 ioport__find_free_port(void) +{ + u16 free_port; + + mutex_lock(&free_io_port_idx_lock); + free_port = IOPORT_START + free_io_port_idx * IOPORT_SIZE; + free_io_port_idx++; + mutex_unlock(&free_io_port_idx_lock); + + return free_port; +} + static struct ioport_entry *ioport_search(struct rb_root *root, u64 addr) { struct rb_int_node *node; @@ -68,10 +83,13 @@ static struct ioport_operations dummy_write_only_ioport_ops = { .io_out = dummy_io_out, }; -void ioport__register(u16 port, struct ioport_operations *ops, int count) +u16 ioport__register(u16 port, struct ioport_operations *ops, int count) { struct ioport_entry *entry; + if (port == IOPORT_EMPTY) + port = ioport__find_free_port(); + entry = ioport_search(&ioport_tree, port); if (entry) { pr_warning("ioport re-registered: %x", port); @@ -88,12 +106,17 @@ void ioport__register(u16 port, struct ioport_operations *ops, int count) }; ioport_insert(&ioport_tree, entry); + + return port; } -void ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param) +u16 ioport__register_param(u16 port, struct ioport_operations *ops, int count, void *param) { struct ioport_entry *entry; + if (port == IOPORT_EMPTY) + port = ioport__find_free_port(); + entry = ioport_search(&ioport_tree, port); if (entry) { pr_warning("ioport re-registered: %x", port); @@ -111,6 +134,8 @@ void ioport__register_param(u16 port, struct ioport_operations *ops, int count, }; ioport_insert(&ioport_tree, entry); + + return port; } static const char *to_direction(int direction) @@ -126,6 +151,13 @@ static void ioport_error(u16 port, void *data, int direction, int size, u32 coun fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count); } +u16 ioport__find_free_range(void) +{ + static u16 cur_loc; + + return IOPORT_START + (cur_loc++ * IOPORT_SIZE); +} + bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count) { struct ioport_operations *ops; -- 1.7.5.rc3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html