[PATCH 09/10] qemu-kvm: Use upstream kvm_cpu_exec

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Upstream's and qemu-kvm's kvm_cpu_exec are not logically equivalent so
that we can safely switch the implementations.

A bit refactoring of kvm_main_loop_cpu is required as upstream's cpu
loop already contains the asynchronous event processing which ran
outside so far.

Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx>
---
 kvm-all.c         |    3 -
 qemu-kvm-x86.c    |  101 +-----------------------
 qemu-kvm.c        |  225 ++++-------------------------------------------------
 qemu-kvm.h        |   44 +----------
 target-i386/kvm.c |    2 -
 5 files changed, 17 insertions(+), 358 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 5ac177f..88d0785 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -958,8 +958,6 @@ void kvm_cpu_synchronize_post_init(CPUState *env)
     env->kvm_vcpu_dirty = 0;
 }
 
-#ifdef OBSOLETE_KVM_IMPL
-
 int kvm_cpu_exec(CPUState *env)
 {
     struct kvm_run *run = env->kvm_run;
@@ -1065,7 +1063,6 @@ int kvm_cpu_exec(CPUState *env)
     return ret;
 }
 
-#endif
 int kvm_ioctl(KVMState *s, int type, ...)
 {
     int ret;
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 18f7c3a..89bb692 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -49,13 +49,13 @@ static int kvm_create_pit(KVMState *s)
 
 #ifdef KVM_EXIT_TPR_ACCESS
 
-static int kvm_handle_tpr_access(CPUState *env)
+int kvm_handle_tpr_access(CPUState *env)
 {
     struct kvm_run *run = env->kvm_run;
     kvm_tpr_access_report(env,
                           run->tpr_access.rip,
                           run->tpr_access.is_write);
-    return 0;
+    return 1;
 }
 
 
@@ -70,41 +70,6 @@ int kvm_enable_vapic(CPUState *env, uint64_t vapic)
 
 #endif
 
-extern CPUState *kvm_debug_cpu_requested;
-
-int kvm_arch_run(CPUState *env)
-{
-    int r = 0;
-    struct kvm_run *run = env->kvm_run;
-
-    switch (run->exit_reason) {
-#ifdef KVM_EXIT_SET_TPR
-    case KVM_EXIT_SET_TPR:
-        break;
-#endif
-#ifdef KVM_EXIT_TPR_ACCESS
-    case KVM_EXIT_TPR_ACCESS:
-        r = kvm_handle_tpr_access(env);
-        break;
-#endif
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-    case KVM_EXIT_DEBUG:
-        DPRINTF("kvm_exit_debug\n");
-        r = kvm_handle_debug(&run->debug.arch);
-        if (r == EXCP_DEBUG) {
-            kvm_debug_cpu_requested = env;
-            env->stopped = 1;
-        }
-        break;
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
-    default:
-        r = -1;
-        break;
-    }
-
-    return r;
-}
-
 #ifdef KVM_CAP_IRQCHIP
 
 int kvm_get_lapic(CPUState *env, struct kvm_lapic_state *s)
@@ -178,11 +143,6 @@ int kvm_set_pit2(KVMState *s, struct kvm_pit_state2 *ps2)
 #endif
 #endif
 
-static void kvm_set_cr8(CPUState *env, uint64_t cr8)
-{
-    env->kvm_run->cr8 = cr8;
-}
-
 #ifdef KVM_CAP_VAPIC
 static int kvm_enable_tpr_access_reporting(CPUState *env)
 {
@@ -207,63 +167,6 @@ static int _kvm_arch_init_vcpu(CPUState *env)
     return 0;
 }
 
-int kvm_arch_halt(CPUState *env)
-{
-
-    if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
-          (env->eflags & IF_MASK)) &&
-        !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 1;
-    }
-    return 1;
-}
-
-void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
-{
-    if (!kvm_irqchip_in_kernel()) {
-        kvm_set_cr8(env, cpu_get_apic_tpr(env->apic_state));
-    }
-}
-
-int kvm_arch_try_push_interrupts(void *opaque)
-{
-    CPUState *env = cpu_single_env;
-    int r, irq;
-
-    if (kvm_is_ready_for_interrupt_injection(env) &&
-        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
-        (env->eflags & IF_MASK)) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        irq = cpu_get_pic_interrupt(env);
-        if (irq >= 0) {
-            r = kvm_inject_irq(env, irq);
-            if (r < 0) {
-                printf("cpu %d fail inject %x\n", env->cpu_index, irq);
-            }
-        }
-    }
-
-    return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
-}
-
-#ifdef KVM_CAP_USER_NMI
-void kvm_arch_push_nmi(void)
-{
-    CPUState *env = cpu_single_env;
-    int r;
-
-    if (likely(!(env->interrupt_request & CPU_INTERRUPT_NMI))) {
-        return;
-    }
-
-    env->interrupt_request &= ~CPU_INTERRUPT_NMI;
-    r = kvm_inject_nmi(env);
-    if (r < 0) {
-        printf("cpu %d fail inject NMI\n", env->cpu_index);
-    }
-}
-#endif /* KVM_CAP_USER_NMI */
-
 #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 void kvm_arch_do_ioperm(void *_data)
 {
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 41c4219..b2387df 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -73,31 +73,6 @@ static QLIST_HEAD(, ioperm_data) ioperm_head;
 
 #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
 
-static int handle_unhandled(uint64_t reason)
-{
-    fprintf(stderr, "kvm: unhandled exit %" PRIx64 "\n", reason);
-    return -EINVAL;
-}
-
-#define VMX_INVALID_GUEST_STATE 0x80000021
-
-static int handle_failed_vmentry(uint64_t reason)
-{
-    fprintf(stderr, "kvm: vm entry failed with error 0x%" PRIx64 "\n\n", reason);
-
-    /* Perhaps we will need to check if this machine is intel since exit reason 0x21
-       has a different interpretation on SVM */
-    if (reason == VMX_INVALID_GUEST_STATE) {
-        fprintf(stderr, "If you're runnning a guest on an Intel machine without\n");
-        fprintf(stderr, "unrestricted mode support, the failure can be most likely\n");
-        fprintf(stderr, "due to the guest entering an invalid state for Intel VT.\n");
-        fprintf(stderr, "For example, the guest maybe running in big real mode\n");
-        fprintf(stderr, "which is not supported on less recent Intel processors.\n\n");
-    }
-
-    return -EINVAL;
-}
-
 static inline void set_gsi(KVMState *s, unsigned int gsi)
 {
     uint32_t *bitmap = s->used_gsi_bitmap;
@@ -244,169 +219,6 @@ int kvm_set_irqchip(KVMState *s, struct kvm_irqchip *chip)
 
 #endif
 
-static int handle_mmio(CPUState *env)
-{
-    unsigned long addr = env->kvm_run->mmio.phys_addr;
-    struct kvm_run *kvm_run = env->kvm_run;
-    void *data = kvm_run->mmio.data;
-
-    /* hack: Red Hat 7.1 generates these weird accesses. */
-    if ((addr > 0xa0000 - 4 && addr <= 0xa0000) && kvm_run->mmio.len == 3) {
-        return 0;
-    }
-
-    cpu_physical_memory_rw(addr, data, kvm_run->mmio.len, kvm_run->mmio.is_write);
-    return 0;
-}
-
-static int handle_shutdown(CPUState *env)
-{
-    /* stop the current vcpu from going back to guest mode */
-    env->stopped = 1;
-
-    qemu_system_reset_request();
-    return 1;
-}
-
-static inline void push_nmi(void)
-{
-#ifdef KVM_CAP_USER_NMI
-    kvm_arch_push_nmi();
-#endif                          /* KVM_CAP_USER_NMI */
-}
-
-static void post_kvm_run(CPUState *env)
-{
-    pthread_mutex_lock(&qemu_mutex);
-    cpu_single_env = env;
-
-    kvm_arch_post_run(env, env->kvm_run);
-}
-
-static void pre_kvm_run(CPUState *env)
-{
-    kvm_arch_pre_run(env, env->kvm_run);
-
-    if (env->exit_request) {
-        qemu_cpu_kick_self();
-    }
-
-    cpu_single_env = NULL;
-    pthread_mutex_unlock(&qemu_mutex);
-}
-
-int kvm_is_ready_for_interrupt_injection(CPUState *env)
-{
-    return env->kvm_run->ready_for_interrupt_injection;
-}
-
-static int kvm_run(CPUState *env)
-{
-    int r;
-    struct kvm_run *run = env->kvm_run;
-
-    cpu_single_env = env;
-
-  again:
-    if (env->kvm_vcpu_dirty) {
-        kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
-        env->kvm_vcpu_dirty = 0;
-    }
-    push_nmi();
-    if (!kvm_state->irqchip_in_kernel) {
-        run->request_interrupt_window = kvm_arch_try_push_interrupts(env);
-    }
-
-    pre_kvm_run(env);
-
-    r = kvm_vcpu_ioctl(env, KVM_RUN, 0);
-
-    post_kvm_run(env);
-
-    kvm_flush_coalesced_mmio_buffer();
-
-    if (r == -EINTR || r == -EAGAIN) {
-        env->exit_request = 0;
-        return 1;
-    }
-    if (r < 0) {
-        fprintf(stderr, "kvm_run: %s\n", strerror(-r));
-        return r;
-    }
-
-    if (1) {
-        switch (run->exit_reason) {
-        case KVM_EXIT_UNKNOWN:
-            r = handle_unhandled(run->hw.hardware_exit_reason);
-            break;
-        case KVM_EXIT_FAIL_ENTRY:
-            r = handle_failed_vmentry(run->fail_entry.hardware_entry_failure_reason);
-            break;
-        case KVM_EXIT_EXCEPTION:
-            fprintf(stderr, "exception %d (%x)\n", run->ex.exception,
-                    run->ex.error_code);
-            cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-            abort();
-            break;
-        case KVM_EXIT_IO:
-            kvm_handle_io(run->io.port,
-                                (uint8_t *)run + run->io.data_offset,
-                                run->io.direction,
-                                run->io.size,
-                                run->io.count);
-            r = 0;
-            break;
-        case KVM_EXIT_MMIO:
-            r = handle_mmio(env);
-            break;
-        case KVM_EXIT_HLT:
-            r = kvm_arch_halt(env);
-            break;
-        case KVM_EXIT_IRQ_WINDOW_OPEN:
-            break;
-        case KVM_EXIT_SHUTDOWN:
-            r = handle_shutdown(env);
-            break;
-	case KVM_EXIT_INTERNAL_ERROR:
-            r = kvm_handle_internal_error(env, run);
-	    break;
-        default:
-            r = kvm_arch_run(env);
-            if (r < 0) {
-                fprintf(stderr, "unhandled vm exit: 0x%x\n", run->exit_reason);
-                cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-                abort();
-            }
-            if (r > 0) {
-                return r;
-            }
-            break;
-        }
-    }
-    if (!r) {
-        goto again;
-    }
-    env->exit_request = 0;
-    return r;
-}
-
-int kvm_inject_irq(CPUState *env, unsigned irq)
-{
-    struct kvm_interrupt intr;
-
-    intr.irq = irq;
-    return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
-}
-
-int kvm_inject_nmi(CPUState *env)
-{
-#ifdef KVM_CAP_USER_NMI
-    return kvm_vcpu_ioctl(env, KVM_NMI);
-#else
-    return -ENOSYS;
-#endif
-}
-
 #ifdef KVM_CAP_DEVICE_ASSIGNMENT
 int kvm_assign_pci_device(KVMState *s,
                           struct kvm_assigned_pci_dev *assigned_dev)
@@ -856,20 +668,6 @@ void kvm_update_interrupt_request(CPUState *env)
     }
 }
 
-int kvm_cpu_exec(CPUState *env)
-{
-    int r;
-
-    r = kvm_run(env);
-    if (r < 0) {
-        printf("kvm_run returned %d\n", r);
-        cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
-        vm_stop(VMSTOP_PANIC);
-    }
-
-    return 0;
-}
-
 static int kvm_cpu_is_stopped(CPUState *env)
 {
     return !vm_running || env->stopped;
@@ -1035,16 +833,21 @@ static void qemu_kvm_system_reset(void)
 static int kvm_main_loop_cpu(CPUState *env)
 {
     while (1) {
-        int run_cpu = !kvm_cpu_is_stopped(env);
-        if (run_cpu) {
-            run_cpu = !kvm_arch_process_async_events(env);
-        }
-        if (run_cpu) {
-            kvm_cpu_exec(env);
-            kvm_main_loop_wait(env, 0);
-        } else {
-            kvm_main_loop_wait(env, 1000);
+        int timeout = 1000;
+        if (!kvm_cpu_is_stopped(env)) {
+            switch (kvm_cpu_exec(env)) {
+            case EXCP_HLT:
+                break;
+            case EXCP_DEBUG:
+                kvm_debug_cpu_requested = env;
+                env->stopped = 1;
+                break;
+            default:
+                timeout = 0;
+                break;
+            }
         }
+        kvm_main_loop_wait(env, timeout);
     }
     pthread_mutex_unlock(&qemu_mutex);
     return 0;
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 5621cfa..57dc6aa 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -37,35 +37,8 @@
 
 #include "kvm.h"
 
-int kvm_arch_run(CPUState *env);
-
 int kvm_create_irqchip(KVMState *s);
 
-/*!
- * \brief Check if a vcpu is ready for interrupt injection
- *
- * This checks if vcpu interrupts are not masked by mov ss or sti.
- *
- * \param kvm Pointer to the current kvm_context
- * \param vcpu Which virtual CPU should get dumped
- * \return boolean indicating interrupt injection readiness
- */
-int kvm_is_ready_for_interrupt_injection(CPUState *env);
-
-#if defined(__i386__) || defined(__x86_64__)
-/*!
- * \brief Simulate an external vectored interrupt
- *
- * This allows you to simulate an external vectored interrupt.
- *
- * \param kvm Pointer to the current kvm_context
- * \param vcpu Which virtual CPU should get dumped
- * \param irq Vector number
- * \return 0 on success
- */
-int kvm_inject_irq(CPUState *env, unsigned irq);
-#endif
-
 #ifdef KVM_CAP_IRQCHIP
 /*!
  * \brief Dump in kernel IRQCHIP contents
@@ -115,17 +88,6 @@ int kvm_set_lapic(CPUState *env, struct kvm_lapic_state *s);
 
 #endif
 
-/*!
- * \brief Simulate an NMI
- *
- * This allows you to simulate a non-maskable interrupt.
- *
- * \param kvm Pointer to the current kvm_context
- * \param vcpu Which virtual CPU should get dumped
- * \return 0 on success
- */
-int kvm_inject_nmi(CPUState *env);
-
 #endif
 
 #ifdef KVM_CAP_PIT
@@ -314,8 +276,6 @@ void kvm_hpet_disable_kpit(void);
 void on_vcpu(CPUState *env, void (*func)(void *data), void *data);
 void kvm_update_interrupt_request(CPUState *env);
 
-int kvm_arch_try_push_interrupts(void *opaque);
-void kvm_arch_push_nmi(void);
 int kvm_set_boot_cpu_id(KVMState *s, uint32_t id);
 
 void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write);
@@ -347,9 +307,7 @@ struct ioperm_data {
     QLIST_ENTRY(ioperm_data) entries;
 };
 
-int kvm_arch_halt(CPUState *env);
-int handle_tpr_access(void *opaque, CPUState *env, uint64_t rip,
-                      int is_write);
+int kvm_handle_tpr_access(CPUState *env);
 
 #else
 #define kvm_nested 0
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e98eccf..bccd87c 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1565,7 +1565,6 @@ int kvm_arch_get_registers(CPUState *env)
     return 0;
 }
 
-#ifdef OBSOLETE_KVM_IMPL
 void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
 {
     int ret;
@@ -1623,7 +1622,6 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
         run->cr8 = cpu_get_apic_tpr(env->apic_state);
     }
 }
-#endif
 
 void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 {
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux