>From 39ca008b144e1e729223b1302fcdd7a435370487 Mon Sep 17 00:00:00 2001
From: Weidong Han <[EMAIL PROTECTED]>
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 <[EMAIL PROTECTED]>
---
 qemu/hw/device-assignment.c |   39 ++++++++++++++++++++-------------------
 qemu/qemu-kvm.c             |   13 +++++++++++++
 qemu/qemu-kvm.h             |    2 ++
 3 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/qemu/hw/device-assignment.c b/qemu/hw/device-assignment.c
index e1c3372..4e10ef7 100644
--- a/qemu/hw/device-assignment.c
+++ b/qemu/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/qemu-kvm.c b/qemu/qemu-kvm.c
index af9ad38..4cd8a2d 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/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 <sys/io.h>
 
 #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/qemu-kvm.h b/qemu/qemu-kvm.h
index 2c1dfa8..4cd4fca 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/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)
-- 
1.5.1

Attachment: 0001-support-ioperm-for-vcpu-hotplug.patch
Description: 0001-support-ioperm-for-vcpu-hotplug.patch

Reply via email to