Commit 3d62dea6 authored by Sasha Levin's avatar Sasha Levin Committed by Will Deacon
Browse files

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: default avatarSasha Levin <levinsasha928@gmail.com>
Signed-off-by: default avatarPekka Enberg <penberg@kernel.org>
parent de960f08
......@@ -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);
}
......@@ -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);
}
......
......@@ -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);
......
#ifndef KVM__IOPORT_H
#define KVM__IOPORT_H
#include "kvm/rbtree-interval.h"
#include <stdbool.h>
#include <asm/types.h>
#include <linux/types.h>
......@@ -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)
{
......
......@@ -2,7 +2,6 @@
#include "kvm/kvm.h"
#include "kvm/util.h"
#include "kvm/rbtree-interval.h"
#include <linux/kvm.h> /* for KVM_EXIT_* */
#include <linux/types.h>
......@@ -13,17 +12,12 @@
#include <stdlib.h>
#include <stdio.h>
#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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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)
......
......@@ -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);
}
......@@ -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);
}
......
......@@ -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);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment