All of lore.kernel.org
 help / color / mirror / Atom feed
From: Glauber Costa <glommer@redhat.com>
To: kvm@vger.kernel.org
Cc: avi@redhat.com
Subject: [PATCH 3/4] provide a kvm-free implementation of apic
Date: Tue,  2 Jun 2009 15:37:49 -0400	[thread overview]
Message-ID: <1243971470-31676-4-git-send-email-glommer@redhat.com> (raw)
In-Reply-To: <1243971470-31676-3-git-send-email-glommer@redhat.com>

Also, provide a kvm_apic that does not depend highly on common code.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/apic.c      |  249 ++++++++++++++++++++++++++++++++++----------------------
 hw/pc.c        |    7 ++-
 hw/pc.h        |    1 +
 qemu-kvm-x86.c |    5 +-
 4 files changed, 162 insertions(+), 100 deletions(-)

diff --git a/hw/apic.c b/hw/apic.c
index c93cbb3..d7af08f 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -852,103 +852,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-#ifdef KVM_CAP_IRQCHIP
-
-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) >> 24;
-    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);
-
-    v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
-    s->count_shift = (v + 1) & 7;
-
-    s->initial_count_load_time = qemu_get_clock(vm_clock);
-    apic_timer_update(s, s->initial_count_load_time);
-}
-
-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 << 24);
-    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
-
-void qemu_kvm_load_lapic(CPUState *env)
-{
-#ifdef KVM_CAP_IRQCHIP
-    if (kvm_enabled() && kvm_vcpu_inited(env) && qemu_kvm_irqchip_in_kernel()) {
-        kvm_kernel_lapic_load_from_user(env->apic_state);
-    }
-#endif
-}
-
-static void apic_save(QEMUFile *f, void *opaque)
+static void apic_save_common(QEMUFile *f, void *opaque)
 {
     APICState *s = opaque;
     int i;
 
-#ifdef KVM_CAP_IRQCHIP
-    if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) {
-        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);
@@ -976,7 +884,12 @@ static void apic_save(QEMUFile *f, void *opaque)
     qemu_put_timer(f, s->timer);
 }
 
-static int apic_load(QEMUFile *f, void *opaque, int version_id)
+static void apic_save(QEMUFile *f, void *opaque)
+{
+    apic_save_common(f, opaque);
+}
+
+static int apic_load_common(QEMUFile *f, void *opaque, int version_id)
 {
     APICState *s = opaque;
     int i;
@@ -1012,12 +925,15 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
     if (version_id >= 2)
         qemu_get_timer(f, s->timer);
 
-    qemu_kvm_load_lapic(s->cpu_env);
-
     return 0;
 }
 
-static void apic_reset(void *opaque)
+static int apic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return apic_load_common(f, opaque, version_id);
+}
+
+static void apic_reset_common(void *opaque)
 {
     APICState *s = opaque;
 
@@ -1034,7 +950,11 @@ static void apic_reset(void *opaque)
          */
         s->lvt[APIC_LVT_LINT0] = 0x700;
     }
-    qemu_kvm_load_lapic(s->cpu_env);
+}
+
+static void apic_reset(void *opaque)
+{
+    apic_reset_common(opaque);
 }
 
 static CPUReadMemoryFunc *apic_mem_read[3] = {
@@ -1081,3 +1001,136 @@ int apic_init(CPUState *env)
     return 0;
 }
 
+#ifdef KVM_CAP_IRQCHIP
+
+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) >> 24;
+    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);
+
+    v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
+    s->count_shift = (v + 1) & 7;
+
+    s->initial_count_load_time = qemu_get_clock(vm_clock);
+    apic_timer_update(s, s->initial_count_load_time);
+}
+
+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 << 24);
+    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 kvm_apic_save(QEMUFile *f, void *opaque)
+{
+    APICState *s = opaque;
+
+    kvm_kernel_lapic_save_to_user(s);
+    apic_save_common(f, opaque);
+}
+
+static int kvm_apic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    APICState *s = opaque;
+    int r = apic_load_common(f, opaque, version_id);
+
+    if (r == 0)
+        qemu_kvm_load_lapic(s->cpu_env);
+    return r;
+}
+
+
+void qemu_kvm_load_lapic(CPUState *env)
+{
+    if (kvm_vcpu_inited(env)) {
+        kvm_kernel_lapic_load_from_user(env->apic_state);
+    }
+}
+
+static void kvm_apic_reset(void *opaque)
+{
+    APICState *s = opaque;
+
+    apic_reset_common(opaque);
+    qemu_kvm_load_lapic(s->cpu_env);
+}
+
+int kvm_apic_init(CPUState *env)
+{
+    APICState *s;
+
+    if (last_apic_id >= MAX_APICS)
+        return -1;
+    s = qemu_mallocz(sizeof(APICState));
+    env->apic_state = s;
+    s->id = last_apic_id++;
+    env->cpuid_apic_id = s->id;
+    s->cpu_env = env;
+
+    kvm_apic_reset(s);
+
+    s->timer = qemu_new_timer(vm_clock, apic_timer, s);
+
+    register_savevm("apic", s->id, 2, kvm_apic_save, kvm_apic_load, s);
+    qemu_register_reset(kvm_apic_reset, 0, s);
+
+    local_apics[s->id] = s;
+    return 0;
+}
diff --git a/hw/pc.c b/hw/pc.c
index 66f4635..a99ab07 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -842,7 +842,12 @@ CPUState *pc_new_cpu(int cpu, const char *cpu_model, int pci_enabled)
         }
         qemu_register_reset(main_cpu_reset, 0, env);
         if (pci_enabled) {
-            apic_init(env);
+#ifdef KVM_CAP_IRQCHIP
+            if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) {
+                kvm_apic_init(env);
+            } else
+#endif
+                apic_init(env);
         }
 
     /* kvm needs this to run after the apic is initialized. Otherwise,
diff --git a/hw/pc.h b/hw/pc.h
index 3af22f2..ab847b9 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -48,6 +48,7 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
                              uint8_t vector_num, uint8_t polarity,
                              uint8_t trigger_mode);
 int apic_init(CPUState *env);
+int kvm_apic_init(CPUState *env);
 int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 98aa530..925d70e 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -527,7 +527,10 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
     CPUState copy;
     uint32_t i, j, limit;
 
-    qemu_kvm_load_lapic(cenv);
+#ifdef KVM_CAP_IRQCHIP
+    if (qemu_kvm_irqchip_in_kernel())
+        qemu_kvm_load_lapic(cenv);
+#endif
 
     copy = *cenv;
 
-- 
1.5.6.6


  reply	other threads:[~2009-06-02 19:37 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-02 19:37 [PATCH 0/4] Provide kvm-free implementations of apic/ioapic Glauber Costa
2009-06-02 19:37 ` [PATCH 1/4] always halt non-bsp cpu Glauber Costa
2009-06-02 19:37   ` [PATCH 2/4] sipi and init: move common code Glauber Costa
2009-06-02 19:37     ` Glauber Costa [this message]
2009-06-02 19:37       ` [PATCH 4/4] provide a kvm-free implementation of ioapic Glauber Costa
2009-06-02 20:35   ` [PATCH 1/4] always halt non-bsp cpu Jan Kiszka
2009-06-02 21:23     ` Glauber Costa
2009-06-02 22:01       ` Jan Kiszka
2009-06-02 22:09         ` Glauber Costa
2009-06-02 22:32           ` Jan Kiszka
2009-06-02 22:40             ` Glauber Costa
2009-06-03  1:01             ` Glauber Costa
2009-06-03 11:03               ` Jan Kiszka
2009-06-03  1:23             ` Glauber Costa
2009-06-03 11:01               ` Jan Kiszka
2009-06-03 11:11                 ` Gleb Natapov
2009-06-03 10:32   ` Gleb Natapov
2009-06-03 18:25 [PATCH 0/4] kvm free implementation of apic/ioapic Glauber Costa
2009-06-03 18:25 ` [PATCH 1/4] avoid halted state for in kernel irqchip Glauber Costa
2009-06-03 18:25   ` [PATCH 2/4] sipi and init: move common code Glauber Costa
2009-06-03 18:25     ` [PATCH 3/4] provide a kvm-free implementation of apic Glauber Costa
2009-06-03 21:19 [PATCH 0/4] apic/ioapic kvm free implementation Glauber Costa
2009-06-03 21:19 ` [PATCH 1/4] avoid halted state for in kernel irqchip Glauber Costa
2009-06-03 21:19   ` [PATCH 2/4] sipi and init: move common code Glauber Costa
2009-06-03 21:19     ` [PATCH 3/4] provide a kvm-free implementation of apic Glauber Costa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1243971470-31676-4-git-send-email-glommer@redhat.com \
    --to=glommer@redhat.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.