qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 12/20] build list of available accelerators


From: Glauber Costa
Subject: [Qemu-devel] [PATCH 12/20] build list of available accelerators
Date: Fri, 27 Jun 2008 17:38:15 -0300

instead of hardcoding kqemu_start() in exec.c, which would require
such a hack for all available accelerators, semantics of register_qemu_accel()
is changed a little bit. It only builds a list of available accelerators.
The last one registered is the first tried.

This is a temporary solution, since we don't control exactly the order in which
things are loaded by the constructor attributes. The final goal is to have 
command
line switches and priority lists to determine that.

"info accelerator" is changed to accomodate it. It now prints a list of 
available
accelerators, and only if one of them is active, a detailed description of it 
is printed.
---
 accel.h   |   43 +++++++++++++++++++++++++++++++++++++++++--
 exec.c    |    4 +---
 kqemu.c   |   11 +++++++++--
 monitor.c |   18 ++++++++++++++++--
 vl.c      |    1 +
 5 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/accel.h b/accel.h
index 9d5b3a2..99f4742 100644
--- a/accel.h
+++ b/accel.h
@@ -1,6 +1,8 @@
 typedef struct QEMUAccel {
+    char *name;
     void (*cpu_interrupt)(CPUState *env);
     void (*init_env)(CPUState *env);
+    int (*start)(void);
     void (*flush_cache)(CPUState *env, int global);
     void (*flush_page)(CPUState *env, target_ulong addr);
     int (*info)(CPUState *env, char *buf);
@@ -10,11 +12,33 @@ typedef struct QEMUAccel {
     uint64_t (*get_real_ticks)(void);
 } QEMUAccel;
 
+typedef struct QEMUCont {
+    QEMUAccel *acc;
+    int active;
+    struct QEMUCont *next;
+} QEMUCont;
+
 extern QEMUAccel *current_accel;
+extern QEMUCont *head;
+void *qemu_mallocz(size_t size);
 
-static inline void register_qemu_accel(QEMUAccel *accel)
+static inline int register_qemu_accel(QEMUAccel *accel)
 {
-    current_accel = accel;
+    QEMUCont *new;
+
+    new = qemu_mallocz(sizeof(*head));
+
+    new->acc = accel;
+    new->active = 0;
+    new->next = head;
+    head = new;
+
+    return 0;
+}
+
+static inline QEMUCont *get_accel_head(void)
+{
+    return head;
 }
 
 static inline void accel_cpu_interrupt(CPUState *env)
@@ -23,6 +47,21 @@ static inline void accel_cpu_interrupt(CPUState *env)
         current_accel->cpu_interrupt(env);
 }
 
+static inline void accel_start(void)
+{
+    /* The top accelerator in the list gets tried first, but if it fails,
+     * keep trying until one of them succeeds or we exhaust the list */
+    QEMUCont *tmp = head;
+    while (tmp) {
+        if (tmp->acc && tmp->acc->start && (!(tmp->acc->start())) ) {
+            tmp->active = 1;
+            current_accel = tmp->acc;
+            break;
+        }
+        tmp = tmp->next;
+    }
+}
+
 static inline void accel_init_env(CPUState *env)
 {
     if (current_accel && current_accel->init_env)
diff --git a/exec.c b/exec.c
index f62508b..e5d3fea 100644
--- a/exec.c
+++ b/exec.c
@@ -435,9 +435,7 @@ void cpu_exec_init_all(unsigned long tb_size)
 #if !defined(CONFIG_USER_ONLY)
     io_mem_init();
 #endif
-#ifdef USE_KQEMU
-    kqemu_start();
-#endif
+    accel_start();
 }
 
 void cpu_exec_init(CPUState *env)
diff --git a/kqemu.c b/kqemu.c
index 9184b26..783b036 100644
--- a/kqemu.c
+++ b/kqemu.c
@@ -155,7 +155,6 @@ static void kqemu_update_cpuid(CPUState *env)
        accelerated code */
 }
 
-QEMUAccel kqemu_accel;
 extern int smp_cpus;
 
 int kqemu_start(void)
@@ -240,7 +239,6 @@ int kqemu_start(void)
     }
     nb_pages_to_flush = 0;
     nb_ram_pages_to_update = 0;
-    register_qemu_accel(&kqemu_accel);
 
     qpi_init();
     return 0;
@@ -436,8 +434,10 @@ void kqemu_set_phys_mem(uint64_t start_addr, ram_addr_t 
size,
 }
 
 QEMUAccel kqemu_accel = {
+    .name = "KQEMU",
     .cpu_interrupt = kqemu_cpu_interrupt,
     .init_env = kqemu_init_env,
+    .start = kqemu_start,
     .flush_cache = kqemu_flush,
     .flush_page = kqemu_flush_page,
     .info = kqemu_info,
@@ -450,6 +450,13 @@ QEMUAccel kqemu_accel = {
     .get_real_ticks = cpu_get_real_ticks,
 };
 
+static void __attribute__((constructor)) register_kqemu(void)
+{
+    if (register_qemu_accel(&kqemu_accel) < 0)
+        fprintf(logfile, "kqemu: could not register accelerator \n");
+}
+
+
 
 struct fpstate {
     uint16_t fpuc;
diff --git a/monitor.c b/monitor.c
index 29a747d..bc5d07b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1218,6 +1218,18 @@ static void mem_info(void)
 }
 #endif
 
+static int do_accel_do_list(void)
+{
+    QEMUCont *tmp;
+    int active = 0;
+    for (tmp= get_accel_head(); tmp != NULL; tmp = tmp->next)
+    {
+        term_printf("%c %s\n", tmp->active ? '*' : ' ', tmp->acc->name);
+        active |= tmp->active;
+    }
+    return active;
+}
+
 #define MAX_BUF 1024
 static void do_info_accelerator(void)
 {
@@ -1231,8 +1243,10 @@ static void do_info_accelerator(void)
         return;
     }
 
-    if (accel_info(env, buf))
-        term_printf(buf);
+    if (do_accel_do_list()) {
+        if (accel_info(env, buf))
+            term_printf(buf);
+    }
     else
         term_printf("No accelerator present\n");
 }
diff --git a/vl.c b/vl.c
index b402197..fd26b92 100644
--- a/vl.c
+++ b/vl.c
@@ -242,6 +242,7 @@ static CPUState *cur_cpu;
 static CPUState *next_cpu;
 static int event_pending = 1;
 QEMUAccel *current_accel;
+QEMUCont *head = NULL;
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
-- 
1.5.5.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]