From e7e1cea67517d166749a6abc0d4d16cde70fa7d3 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 26 May 2011 13:30:04 +0300 Subject: [PATCH] kvm tools: Add optional parameter used in ioport callbacks Allow specifying an optional parameter when registering an ioport range. The callback functions provided by the registering module will be called with the same parameter. This may be used to keep context during callbacks on IO operations. Signed-off-by: Sasha Levin Signed-off-by: Pekka Enberg --- tools/kvm/hw/rtc.c | 10 ++--- tools/kvm/hw/serial.c | 6 +-- tools/kvm/hw/vesa.c | 6 +-- tools/kvm/include/kvm/ioport.h | 14 +++++-- tools/kvm/ioport.c | 71 +++++++++++++++------------------- tools/kvm/pci.c | 12 +++--- tools/kvm/virtio/9p.c | 6 +-- tools/kvm/virtio/blk.c | 6 +-- tools/kvm/virtio/console.c | 6 +-- tools/kvm/virtio/net.c | 6 +-- tools/kvm/virtio/rng.c | 6 +-- 11 files changed, 74 insertions(+), 75 deletions(-) diff --git a/tools/kvm/hw/rtc.c b/tools/kvm/hw/rtc.c index 6735e8223230..146f66077f0c 100644 --- a/tools/kvm/hw/rtc.c +++ b/tools/kvm/hw/rtc.c @@ -19,7 +19,7 @@ static inline unsigned char bin2bcd(unsigned val) return ((val / 10) << 4) + val % 10; } -static bool cmos_ram_data_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool cmos_ram_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { struct tm *tm; time_t ti; @@ -52,7 +52,7 @@ static bool cmos_ram_data_in(struct kvm *kvm, u16 port, void *data, int size, u3 return true; } -static bool cmos_ram_data_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool cmos_ram_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } @@ -62,7 +62,7 @@ static struct ioport_operations cmos_ram_data_ioport_ops = { .io_in = cmos_ram_data_in, }; -static bool cmos_ram_index_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool cmos_ram_index_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { u8 value; @@ -82,6 +82,6 @@ static struct ioport_operations cmos_ram_index_ioport_ops = { void rtc__init(void) { /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ - ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1); - ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1); + ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1, NULL); + ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1, NULL); } diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c index beebbba5d960..1199264e12e2 100644 --- a/tools/kvm/hw/serial.c +++ b/tools/kvm/hw/serial.c @@ -164,7 +164,7 @@ static struct serial8250_device *find_device(u16 port) return NULL; } -static bool serial8250_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { struct serial8250_device *dev; u16 offset; @@ -252,7 +252,7 @@ out_unlock: return ret; } -static bool serial8250_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { struct serial8250_device *dev; u16 offset; @@ -339,7 +339,7 @@ static struct ioport_operations serial8250_ops = { static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) { - ioport__register(dev->iobase, &serial8250_ops, 8); + ioport__register(dev->iobase, &serial8250_ops, 8, NULL); kvm__irq_line(kvm, dev->irq, 0); } diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c index 6ab07eee656f..ec4788c1d377 100644 --- a/tools/kvm/hw/vesa.c +++ b/tools/kvm/hw/vesa.c @@ -26,12 +26,12 @@ static char videomem[VESA_MEM_SIZE]; -static bool vesa_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } -static bool vesa_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } @@ -75,7 +75,7 @@ void vesa__init(struct kvm *kvm) pci__register(&vesa_pci_device, dev); - ioport__register(IOPORT_VESA, &vesa_io_ops, IOPORT_VESA_SIZE); + ioport__register(IOPORT_VESA, &vesa_io_ops, IOPORT_VESA_SIZE, NULL); kvm__register_mmio(VESA_MEM_ADDR, VESA_MEM_SIZE, &vesa_mmio_callback); diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h index 8253938308f2..67b4a6facc19 100644 --- a/tools/kvm/include/kvm/ioport.h +++ b/tools/kvm/include/kvm/ioport.h @@ -1,6 +1,8 @@ #ifndef KVM__IOPORT_H #define KVM__IOPORT_H +#include "kvm/rbtree-interval.h" + #include #include #include @@ -22,14 +24,20 @@ struct kvm; +struct ioport { + struct rb_int_node node; + struct ioport_operations *ops; + void *priv; +}; + struct ioport_operations { - bool (*io_in)(struct kvm *kvm, u16 port, void *data, int size, u32 count); - bool (*io_out)(struct kvm *kvm, u16 port, void *data, int size, u32 count); + bool (*io_in)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count); + bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count); }; void ioport__setup_legacy(void); -void ioport__register(u16 port, struct ioport_operations *ops, int count); +void ioport__register(u16 port, struct ioport_operations *ops, int count, void *param); static inline u8 ioport__read8(u8 *data) { diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c index 1f139603a56c..92ad15297d96 100644 --- a/tools/kvm/ioport.c +++ b/tools/kvm/ioport.c @@ -2,7 +2,6 @@ #include "kvm/kvm.h" #include "kvm/util.h" -#include "kvm/rbtree-interval.h" #include /* for KVM_EXIT_* */ #include @@ -13,17 +12,12 @@ #include #include -#define ioport_node(n) rb_entry(n, struct ioport_entry, node) - -struct ioport_entry { - struct rb_int_node node; - struct ioport_operations *ops; -}; +#define ioport_node(n) rb_entry(n, struct ioport, node) static struct rb_root ioport_tree = RB_ROOT; bool ioport_debug; -static struct ioport_entry *ioport_search(struct rb_root *root, u64 addr) +static struct ioport *ioport_search(struct rb_root *root, u64 addr) { struct rb_int_node *node; @@ -34,12 +28,12 @@ static struct ioport_entry *ioport_search(struct rb_root *root, u64 addr) return ioport_node(node); } -static int ioport_insert(struct rb_root *root, struct ioport_entry *data) +static int ioport_insert(struct rb_root *root, struct ioport *data) { return rb_int_insert(root, &data->node); } -static bool debug_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { exit(EXIT_SUCCESS); } @@ -48,12 +42,12 @@ static struct ioport_operations debug_ops = { .io_out = debug_io_out, }; -static bool dummy_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } -static bool dummy_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } @@ -67,9 +61,9 @@ 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) +void ioport__register(u16 port, struct ioport_operations *ops, int count, void *param) { - struct ioport_entry *entry; + struct ioport *entry; entry = ioport_search(&ioport_tree, port); if (entry) { @@ -81,9 +75,10 @@ void ioport__register(u16 port, struct ioport_operations *ops, int count) if (entry == NULL) die("Failed allocating new ioport entry"); - *entry = (struct ioport_entry) { + *entry = (struct ioport) { .node = RB_INT_INIT(port, port + count), .ops = ops, + .priv = param, }; ioport_insert(&ioport_tree, entry); @@ -105,30 +100,26 @@ static void ioport_error(u16 port, void *data, int direction, int size, u32 coun bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count) { struct ioport_operations *ops; - bool ret; - struct ioport_entry *entry; + bool ret = false; + struct ioport *entry; entry = ioport_search(&ioport_tree, port); if (!entry) goto error; - ops = entry->ops; + ops = entry->ops; if (direction == KVM_EXIT_IO_IN) { - if (!ops->io_in) - goto error; - - ret = ops->io_in(kvm, port, data, size, count); - if (!ret) - goto error; + if (ops->io_in) + ret = ops->io_in(entry, kvm, port, data, size, count); } else { - if (!ops->io_out) - goto error; - - ret = ops->io_out(kvm, port, data, size, count); - if (!ret) - goto error; + if (ops->io_out) + ret = ops->io_out(entry, kvm, port, data, size, count); } + + if (!ret) + goto error; + return true; error: if (ioport_debug) @@ -140,29 +131,29 @@ error: void ioport__setup_legacy(void) { /* 0x0020 - 0x003F - 8259A PIC 1 */ - ioport__register(0x0020, &dummy_read_write_ioport_ops, 2); + ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL); /* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */ - ioport__register(0x0040, &dummy_read_write_ioport_ops, 4); + ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL); /* PORT 0060-006F - KEYBOARD CONTROLLER 804x (8041, 8042) (or PPI (8255) on PC,XT) */ - ioport__register(0x0060, &dummy_read_write_ioport_ops, 2); - ioport__register(0x0064, &dummy_read_write_ioport_ops, 1); + ioport__register(0x0060, &dummy_read_write_ioport_ops, 2, NULL); + ioport__register(0x0064, &dummy_read_write_ioport_ops, 1, NULL); /* 0x00A0 - 0x00AF - 8259A PIC 2 */ - ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2); + ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL); /* PORT 00E0-00EF are 'motherboard specific' so we use them for our internal debugging purposes. */ - ioport__register(IOPORT_DBG, &debug_ops, 1); + ioport__register(IOPORT_DBG, &debug_ops, 1, NULL); /* PORT 00ED - DUMMY PORT FOR DELAY??? */ - ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1); + ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL); /* 0x00F0 - 0x00FF - Math co-processor */ - ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2); + ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL); /* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */ - ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1); - ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1); + ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL); + ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL); } diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c index d4fbeab83857..a1ad8bae3ac2 100644 --- a/tools/kvm/pci.c +++ b/tools/kvm/pci.c @@ -21,7 +21,7 @@ static void *pci_config_address_ptr(u16 port) return base + offset; } -static bool pci_config_address_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { void *p = pci_config_address_ptr(port); @@ -30,7 +30,7 @@ static bool pci_config_address_out(struct kvm *kvm, u16 port, void *data, int si return true; } -static bool pci_config_address_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { void *p = pci_config_address_ptr(port); @@ -44,7 +44,7 @@ static struct ioport_operations pci_config_address_ops = { .io_out = pci_config_address_out, }; -static bool pci_config_data_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { return true; } @@ -67,7 +67,7 @@ static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_numbe return dev != NULL; } -static bool pci_config_data_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long start; u8 dev_num; @@ -110,6 +110,6 @@ void pci__register(struct pci_device_header *dev, u8 dev_num) void pci__init(void) { - ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4); - ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4); + ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL); + ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL); } diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c index e307592583a1..c4410891d46d 100644 --- a/tools/kvm/virtio/9p.c +++ b/tools/kvm/virtio/9p.c @@ -91,7 +91,7 @@ static bool virtio_p9_dev_in(void *data, unsigned long offset, int size, u32 cou return true; } -static bool virtio_p9_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_p9_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset; bool ret = true; @@ -579,7 +579,7 @@ static void virtio_p9_do_io(struct kvm *kvm, void *param) } } -static bool virtio_p9_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset; bool ret = true; @@ -664,5 +664,5 @@ void virtio_9p__init(struct kvm *kvm, const char *root) virtio_p9_pci_device.irq_line = line; pci__register(&virtio_p9_pci_device, dev); - ioport__register(IOPORT_VIRTIO_P9, &virtio_p9_io_ops, IOPORT_VIRTIO_P9_SIZE); + ioport__register(IOPORT_VIRTIO_P9, &virtio_p9_io_ops, IOPORT_VIRTIO_P9_SIZE, NULL); } diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c index 25ce61f8ef53..5720c7f59467 100644 --- a/tools/kvm/virtio/blk.c +++ b/tools/kvm/virtio/blk.c @@ -73,7 +73,7 @@ static void virtio_blk_port2dev(u16 port, u16 base, u16 size, u16 *dev_idx, u16 *offset = port - (base + *dev_idx * size); } -static bool virtio_blk_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_blk_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { struct blk_dev *bdev; u16 offset, dev_idx; @@ -178,7 +178,7 @@ static void virtio_blk_do_io(struct kvm *kvm, void *param) virt_queue__trigger_irq(vq, bdev->pci_hdr.irq_line, &bdev->isr, kvm); } -static bool virtio_blk_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { struct blk_dev *bdev; u16 offset, dev_idx; @@ -318,7 +318,7 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk) pci__register(&bdev->pci_hdr, dev); - ioport__register(blk_dev_base_addr, &virtio_blk_io_ops, IOPORT_VIRTIO_BLK_SIZE); + ioport__register(blk_dev_base_addr, &virtio_blk_io_ops, IOPORT_VIRTIO_BLK_SIZE, NULL); } void virtio_blk__init_all(struct kvm *kvm) diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c index affff0bc0328..614f0d2b6416 100644 --- a/tools/kvm/virtio/console.c +++ b/tools/kvm/virtio/console.c @@ -111,7 +111,7 @@ static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long o return true; } -static bool virtio_console_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_console_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset = port - IOPORT_VIRTIO_CONSOLE; bool ret = true; @@ -179,7 +179,7 @@ static void virtio_console_handle_callback(struct kvm *kvm, void *param) } -static bool virtio_console_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset = port - IOPORT_VIRTIO_CONSOLE; bool ret = true; @@ -250,5 +250,5 @@ void virtio_console__init(struct kvm *kvm) virtio_console_pci_device.irq_pin = pin; virtio_console_pci_device.irq_line = line; pci__register(&virtio_console_pci_device, dev); - ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE); + ioport__register(IOPORT_VIRTIO_CONSOLE, &virtio_console_io_ops, IOPORT_VIRTIO_CONSOLE_SIZE, NULL); } diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index 649bc0feabc1..014205b09557 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -164,7 +164,7 @@ static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offse return true; } -static bool virtio_net_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_net_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset = port - IOPORT_VIRTIO_NET; bool ret = true; @@ -228,7 +228,7 @@ static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index) } } -static bool virtio_net_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_net_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset = port - IOPORT_VIRTIO_NET; bool ret = true; @@ -394,7 +394,7 @@ void virtio_net__init(const struct virtio_net_parameters *params) pci_header.irq_pin = pin; pci_header.irq_line = line; pci__register(&pci_header, dev); - ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE); + ioport__register(IOPORT_VIRTIO_NET, &virtio_net_io_ops, IOPORT_VIRTIO_NET_SIZE, NULL); virtio_net__io_thread_init(params->kvm); } diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c index 9bd009894c7b..a553f6b7918e 100644 --- a/tools/kvm/virtio/rng.c +++ b/tools/kvm/virtio/rng.c @@ -48,7 +48,7 @@ struct rng_dev { static struct rng_dev rdev; -static bool virtio_rng_pci_io_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_rng_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset; bool ret = true; @@ -111,7 +111,7 @@ static void virtio_rng_do_io(struct kvm *kvm, void *param) } } -static bool virtio_rng_pci_io_out(struct kvm *kvm, u16 port, void *data, int size, u32 count) +static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long offset; bool ret = true; @@ -179,5 +179,5 @@ void virtio_rng__init(struct kvm *kvm) virtio_rng_pci_device.irq_line = line; pci__register(&virtio_rng_pci_device, dev); - ioport__register(IOPORT_VIRTIO_RNG, &virtio_rng_io_ops, IOPORT_VIRTIO_RNG_SIZE); + ioport__register(IOPORT_VIRTIO_RNG, &virtio_rng_io_ops, IOPORT_VIRTIO_RNG_SIZE, NULL); } -- 2.39.5