pci__init();
+ r = ioport__init(kvm);
+ if (r < 0) {
+ pr_err("ioport__init() failed with error %d\n", r);
+ goto fail;
+ }
+
/*
* vidmode should be either specified
* either set by default
disk_image__close_all(kvm->disks, image_count);
free(kvm_cpus);
+
+ r = ioport__exit(kvm);
+ if (r < 0)
+ pr_warning("ioport__exit() failed with error %d\n", r);
+
kvm__delete(kvm);
if (guest_ret == 0)
{
u8 dev, line, pin;
char *mem;
+ int r;
if (shmem_region == 0)
return 0;
pci_shmem_pci_device.irq_line = line;
/* Register MMIO space for MSI-X */
- ivshmem_registers = ioport__register(IOPORT_EMPTY, &shmem_pci__io_ops, IOPORT_SIZE, NULL);
+ r = ioport__register(IOPORT_EMPTY, &shmem_pci__io_ops, IOPORT_SIZE, NULL);
+ if (r < 0)
+ return r;
+ ivshmem_registers = (u16)r;
+
msix_block = pci_get_io_space_block(0x1010);
kvm__register_mmio(kvm, msix_block, 0x1010, false, callback_mmio_msix, NULL);
if (r < 0)
return ERR_PTR(r);
+ r = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
+ if (r < 0)
+ return ERR_PTR(r);
+
vesa_pci_device.irq_pin = pin;
vesa_pci_device.irq_line = line;
- vesa_base_addr = ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
+ vesa_base_addr = (u16)r;
vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
pci__register(&vesa_pci_device, dev);
void ioport__setup_arch(void);
-u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
+int ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
+int ioport__unregister(u16 port);
+int ioport__init(struct kvm *kvm);
+int ioport__exit(struct kvm *kvm);
static inline u8 ioport__read8(u8 *data)
{
#include <linux/types.h>
#define RB_INT_INIT(l, h) (struct rb_int_node){.low = l, .high = h}
+#define rb_int(n) rb_entry(n, struct rb_int_node, node)
struct rb_int_node {
struct rb_node node;
return rb_int_insert(root, &data->node);
}
-u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
+static void ioport_remove(struct rb_root *root, struct ioport *data)
+{
+ rb_int_erase(root, &data->node);
+}
+
+int ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
{
struct ioport *entry;
entry = malloc(sizeof(*entry));
if (entry == NULL)
- die("Failed allocating new ioport entry");
+ return -ENOMEM;
*entry = (struct ioport) {
.node = RB_INT_INIT(port, port + count),
return port;
}
+int ioport__unregister(u16 port)
+{
+ struct ioport *entry;
+ int r;
+
+ br_write_lock();
+
+ r = -ENOENT;
+ entry = ioport_search(&ioport_tree, port);
+ if (!entry)
+ goto done;
+
+ ioport_remove(&ioport_tree, entry);
+
+ free(entry);
+
+ r = 0;
+
+done:
+ br_write_unlock();
+
+ return r;
+}
+
+static void ioport__unregister_all(void)
+{
+ struct ioport *entry;
+ struct rb_node *rb;
+ struct rb_int_node *rb_node;
+
+ rb = rb_first(&ioport_tree);
+ while (rb) {
+ rb_node = rb_int(rb);
+ entry = ioport_node(rb_node);
+ ioport_remove(&ioport_tree, entry);
+ free(entry);
+ rb = rb_first(&ioport_tree);
+ }
+}
+
static const char *to_direction(int direction)
{
if (direction == KVM_EXIT_IO_IN)
return !ioport_debug;
}
+
+int ioport__init(struct kvm *kvm)
+{
+ return 0;
+}
+
+int ioport__exit(struct kvm *kvm)
+{
+ ioport__unregister_all();
+ return 0;
+}
#include <kvm/rbtree-interval.h>
#include <stddef.h>
-#define rb_int(n) rb_entry(n, struct rb_int_node, node)
-
struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point)
{
struct rb_node *node = root->rb_node;
{
struct virtio_pci *vpci = vtrans->virtio;
u8 pin, line, ndev;
+ int r;
vpci->dev = dev;
vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2);
- vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
+ r = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
+ if (r < 0)
+ return r;
+
+ vpci->base_addr = (u16)r;
kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE, false, callback_mmio_table, vpci);
vpci->pci_hdr = (struct pci_device_header) {