kvm: qemu: in-kernel LAPIC live migration support
    
    This patch adds the live migration support for in-kernel LAPICs. The
kernel
    and qemu has different data structures, kernel saves the apic to the
userspace
    as a apic page while qemu uses separate varaibles. The translation
is done in
    this patch. Like PIC/IOAPIC, the save/restore uses original qemu
savevm
    
    Signed-off-by: Yaozu (Eddie) Dong <[EMAIL PROTECTED]>
    Signed-off-by: Qing He <[EMAIL PROTECTED]>

---
 qemu/hw/apic.c |   99
+++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 95 insertions(+), 4 deletions(-)

diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c
index 1f2d977..fb6b1e6 100644
--- a/qemu/hw/apic.c
+++ b/qemu/hw/apic.c
@@ -19,6 +19,12 @@
  */
 #include "vl.h"
 
+#ifdef USE_KVM
+#include "qemu-kvm.h"
+extern int kvm_allowed;
+extern kvm_context_t kvm_context;
+#endif
+
 //#define DEBUG_APIC
 //#define DEBUG_IOAPIC
 
@@ -740,11 +746,93 @@ static void apic_mem_writel(void *opaque,
target_phys_addr_t addr, uint32_t val)
     }
 }
 
+#ifdef USE_KVM
+static inline uint32_t kapic_reg(struct kvm_lapic_state *kapic, int
reg_id)
+{
+    return *((uint32_t *) (kapic->regs + (reg_id << 4)));
+}
+
+static inline void kapic_set_reg(struct kvm_lapic_state *kapic,
+                                 int reg_id, uint32_t val)
+{
+    *((uint32_t *) (kapic->regs + (reg_id << 4))) = val;
+}
+
+static void kvm_kernel_lapic_save_to_user(APICState *s)
+{
+    struct kvm_lapic_state apic;
+    struct kvm_lapic_state *kapic = &apic;
+    int i, v;
+
+    kvm_get_lapic(kvm_context, s->cpu_env->cpu_index, kapic);
+
+    s->id = kapic_reg(kapic, 0x2);
+    s->tpr = kapic_reg(kapic, 0x8);
+    s->arb_id = kapic_reg(kapic, 0x9);
+    s->log_dest = kapic_reg(kapic, 0xd) >> 24;
+    s->dest_mode = kapic_reg(kapic, 0xe) >> 28;
+    s->spurious_vec = kapic_reg(kapic, 0xf);
+    for (i = 0; i < 8; i++) {
+        s->isr[i] = kapic_reg(kapic, 0x10 + i);
+        s->tmr[i] = kapic_reg(kapic, 0x18 + i);
+        s->irr[i] = kapic_reg(kapic, 0x20 + i);
+    }
+    s->esr = kapic_reg(kapic, 0x28);
+    s->icr[0] = kapic_reg(kapic, 0x30);
+    s->icr[1] = kapic_reg(kapic, 0x31);
+    for (i = 0; i < APIC_LVT_NB; i++)
+       s->lvt[i] = kapic_reg(kapic, 0x32 + i);
+    s->initial_count = kapic_reg(kapic, 0x38);
+    s->divide_conf = kapic_reg(kapic, 0x3e);
+    s->initial_count_load_time = qemu_get_clock(vm_clock);
+    s->next_time = s->initial_count_load_time;
+
+    v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
+    s->count_shift = (v + 1) & 7;
+
+    qemu_del_timer(s->timer);
+}
+
+static void kvm_kernel_lapic_load_from_user(APICState *s)
+{
+    struct kvm_lapic_state apic;
+    struct kvm_lapic_state *klapic = &apic;
+    int i;
+
+    memset(klapic, 0, sizeof apic);
+    kapic_set_reg(klapic, 0x2, s->id);
+    kapic_set_reg(klapic, 0x8, s->tpr);
+    kapic_set_reg(klapic, 0xd, s->log_dest << 24);
+    kapic_set_reg(klapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
+    kapic_set_reg(klapic, 0xf, s->spurious_vec);
+    for (i = 0; i < 8; i++) {
+        kapic_set_reg(klapic, 0x10 + i, s->isr[i]);
+        kapic_set_reg(klapic, 0x18 + i, s->tmr[i]);
+        kapic_set_reg(klapic, 0x20 + i, s->irr[i]);
+    }
+    kapic_set_reg(klapic, 0x28, s->esr);
+    kapic_set_reg(klapic, 0x30, s->icr[0]);
+    kapic_set_reg(klapic, 0x31, s->icr[1]);
+    for (i = 0; i < APIC_LVT_NB; i++)
+        kapic_set_reg(klapic, 0x32 + i, s->lvt[i]);
+    kapic_set_reg(klapic, 0x38, s->initial_count);
+    kapic_set_reg(klapic, 0x3e, s->divide_conf);
+
+    kvm_set_lapic(kvm_context, s->cpu_env->cpu_index, klapic);
+}
+#endif
+
 static void apic_save(QEMUFile *f, void *opaque)
 {
     APICState *s = opaque;
     int i;
 
+#ifdef USE_KVM
+    if (kvm_allowed && kvm_irqchip_in_kernel(kvm_context)) {
+        kvm_kernel_lapic_save_to_user(s);
+    }
+#endif
+
     qemu_put_be32s(f, &s->apicbase);
     qemu_put_8s(f, &s->id);
     qemu_put_8s(f, &s->arb_id);
@@ -807,6 +895,13 @@ static int apic_load(QEMUFile *f, void *opaque, int
version_id)
 
     if (version_id >= 2)
         qemu_get_timer(f, s->timer);
+
+#ifdef USE_KVM
+    if (kvm_allowed && kvm_irqchip_in_kernel(kvm_context)) {
+        kvm_kernel_lapic_load_from_user(s);
+    }
+#endif
+
     return 0;
 }
 
@@ -1013,10 +1108,6 @@ static void ioapic_mem_writel(void *opaque,
target_phys_addr_t addr, uint32_t va
 }
 
 #ifdef USE_KVM
-#include "qemu-kvm.h"
-extern int kvm_allowed;
-extern kvm_context_t kvm_context;
-
 static void kvm_kernel_ioapic_save_to_user(IOAPICState *s)
 {
     struct kvm_irqchip chip;

Attachment: kvm-qemu-lapic-lm.patch
Description: kvm-qemu-lapic-lm.patch

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to