From 29419413070920758f95e20b73c9571fdae1badf Mon Sep 17 00:00:00 2001 From: Weidong Han Date: Mon, 10 Nov 2008 14:33:43 +0800 Subject: [PATCH] Support ioperm for vcpu hotplug Track ioperm settings, when a new VCPU comes online, issue ioperm. Signed-off-by: Weidong Han Signed-off-by: Avi Kivity --- hw/device-assignment.c | 39 ++++++++++++++++++++------------------- qemu-kvm.c | 13 +++++++++++++ qemu-kvm.h | 2 ++ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index e1c33722e4..9aa7708f07 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -174,10 +174,7 @@ static void assigned_dev_ioport_map(PCIDevice *pci_dev, int region_num, { AssignedDevice *r_dev = (AssignedDevice *) pci_dev; AssignedDevRegion *region = &r_dev->v_addrs[region_num]; - uint32_t old_port = region->u.r_baseport; - uint32_t old_num = region->e_size; - int first_map = (old_num == 0); - struct ioperm_data data; + int first_map = (region->e_size == 0); int i; region->e_physbase = addr; @@ -186,24 +183,25 @@ static void assigned_dev_ioport_map(PCIDevice *pci_dev, int region_num, DEBUG("e_phys=0x%x r_baseport=%x type=0x%x len=%d region_num=%d \n", addr, region->u.r_baseport, type, size, region_num); - memset(&data, 0, sizeof(data)); + if (first_map) { + struct ioperm_data *data; + + data = qemu_mallocz(sizeof(struct ioperm_data)); + if (data == NULL) { + fprintf(stderr, "%s: Out of memory\n", __func__); + exit(1); + } - if (!first_map) { - data.start_port = old_port; - data.num = old_num; - data.turn_on = 0; + data->start_port = region->u.r_baseport; + data->num = region->r_size; + data->turn_on = 1; + + kvm_add_ioperm_data(data); for (i = 0; i < smp_cpus; ++i) - kvm_ioperm(qemu_kvm_cpu_env(i), &data); + kvm_ioperm(qemu_kvm_cpu_env(i), data); } - data.start_port = region->u.r_baseport; - data.num = size; - data.turn_on = 1; - - for (i = 0; i < smp_cpus; ++i) - kvm_ioperm(qemu_kvm_cpu_env(i), &data); - register_ioport_read(addr, size, 1, assigned_dev_ioport_readb, (r_dev->v_addrs + region_num)); register_ioport_read(addr, size, 2, assigned_dev_ioport_readw, @@ -350,12 +348,15 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, continue; } /* handle port io regions */ + pci_dev->v_addrs[i].e_physbase = cur_region->base_addr; + pci_dev->v_addrs[i].u.r_baseport = cur_region->base_addr; + pci_dev->v_addrs[i].r_size = cur_region->size; + pci_dev->v_addrs[i].e_size = 0; + pci_register_io_region((PCIDevice *) pci_dev, i, cur_region->size, PCI_ADDRESS_SPACE_IO, assigned_dev_ioport_map); - pci_dev->v_addrs[i].e_physbase = cur_region->base_addr; - pci_dev->v_addrs[i].u.r_baseport = cur_region->base_addr; /* not relevant for port io */ pci_dev->v_addrs[i].memory_index = 0; } diff --git a/qemu-kvm.c b/qemu-kvm.c index af9ad38e0b..4cd8a2dc63 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -74,6 +74,9 @@ static int io_thread_sigfd = -1; static int kvm_debug_stop_requested; +/* The list of ioperm_data */ +static LIST_HEAD(, ioperm_data) ioperm_head; + static inline unsigned long kvm_get_thread_id(void) { return syscall(SYS_gettid); @@ -441,6 +444,7 @@ static void *ap_main_loop(void *_env) { CPUState *env = _env; sigset_t signals; + struct ioperm_data *data; vcpu = &vcpu_info[env->cpu_index]; vcpu->env = env; @@ -450,6 +454,10 @@ static void *ap_main_loop(void *_env) kvm_create_vcpu(kvm_context, env->cpu_index); kvm_qemu_init_env(env); + /* do ioperm for io ports of assigned devices */ + LIST_FOREACH(data, &ioperm_head, entries) + on_vcpu(env, kvm_arch_do_ioperm, data); + /* signal VCPU creation */ pthread_mutex_lock(&qemu_mutex); vcpu->created = 1; @@ -1052,6 +1060,11 @@ int qemu_kvm_unregister_coalesced_mmio(target_phys_addr_t addr, #include #ifdef USE_KVM_DEVICE_ASSIGNMENT +void kvm_add_ioperm_data(struct ioperm_data *data) +{ + LIST_INSERT_HEAD(&ioperm_head, data, entries); +} + void kvm_ioperm(CPUState *env, void *data) { if (kvm_enabled() && qemu_system_ready) diff --git a/qemu-kvm.h b/qemu-kvm.h index 2c1dfa8ac9..4cd4fca954 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -107,6 +107,7 @@ int handle_powerpc_dcr_write(int vcpu,uint32_t dcrn, uint32_t data); #ifdef USE_KVM #include "libkvm.h" +#include "sys-queue.h" extern int kvm_allowed; extern kvm_context_t kvm_context; @@ -115,6 +116,7 @@ struct ioperm_data { unsigned long start_port; unsigned long num; int turn_on; + LIST_ENTRY(ioperm_data) entries; }; #define kvm_enabled() (kvm_allowed) -- 2.11.4.GIT