qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [5573] Make DMA bottom-half driven (v2)


From: Anthony Liguori
Subject: [Qemu-devel] [5573] Make DMA bottom-half driven (v2)
Date: Fri, 31 Oct 2008 17:25:57 +0000

Revision: 5573
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5573
Author:   aliguori
Date:     2008-10-31 17:25:56 +0000 (Fri, 31 Oct 2008)

Log Message:
-----------
Make DMA bottom-half driven (v2)

The current DMA routines are driven by a call in main_loop_wait() after every
select.

This patch converts the DMA code to be driven by a constantly rescheduled
bottom half.  The advantage of using a scheduled bottom half is that we can
stop scheduling the bottom half when there no DMA channels are runnable.  This
means we can potentially detect this case and sleep longer in the main loop.

The only two architectures implementing DMA_run() are cris and i386.  For cris,
I converted it to a simple repeating bottom half.  I've only compile tested
this as cris does not seem to work on a 64-bit host.  It should be functionally
identical to the previous implementation so I expect it to work.

For x86, I've made sure to only fire the DMA bottom half if there is a DMA
channel that is runnable.  The effect of this is that unless you're using sb16
or a floppy disk, the DMA bottom half never fires.

You probably should test this malc.  My own benchmarks actually show slight
improvement by it's possible the change in timing could affect your demos.

Since v1, I've changed the code to use a BH instead of a timer.  cris at least
seems to depend on faster than 10ms polling.

Signed-off-by: Anthony Liguori <address@hidden>

Modified Paths:
--------------
    trunk/hw/an5206.c
    trunk/hw/dma.c
    trunk/hw/etraxfs_dma.c
    trunk/hw/integratorcp.c
    trunk/hw/isa.h
    trunk/hw/shix.c
    trunk/hw/sun4m.c
    trunk/hw/sun4u.c
    trunk/vl.c

Modified: trunk/hw/an5206.c
===================================================================
--- trunk/hw/an5206.c   2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/an5206.c   2008-10-31 17:25:56 UTC (rev 5573)
@@ -24,10 +24,6 @@
 {
 }
 
-void DMA_run (void)
-{
-}
-
 /* Board init.  */
 
 static void an5206_init(ram_addr_t ram_size, int vga_ram_size,

Modified: trunk/hw/dma.c
===================================================================
--- trunk/hw/dma.c      2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/dma.c      2008-10-31 17:25:56 UTC (rev 5573)
@@ -78,6 +78,8 @@
 
 };
 
+static void DMA_run (void);
+
 static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
 
 static void write_page (void *opaque, uint32_t nport, uint32_t data)
@@ -214,6 +216,7 @@
             d->status &= ~(1 << (ichan + 4));
         }
         d->status &= ~(1 << ichan);
+        DMA_run();
         break;
 
     case 0x0a:                  /* single mask */
@@ -221,6 +224,7 @@
             d->mask |= 1 << (data & 3);
         else
             d->mask &= ~(1 << (data & 3));
+        DMA_run();
         break;
 
     case 0x0b:                  /* mode */
@@ -255,10 +259,12 @@
 
     case 0x0e:                  /* clear mask for all channels */
         d->mask = 0;
+        DMA_run();
         break;
 
     case 0x0f:                  /* write mask for all channels */
         d->mask = data;
+        DMA_run();
         break;
 
     default:
@@ -310,6 +316,7 @@
     ichan = nchan & 3;
     linfo ("held cont=%d chan=%d\n", ncont, ichan);
     dma_controllers[ncont].status |= 1 << (ichan + 4);
+    DMA_run();
 }
 
 void DMA_release_DREQ (int nchan)
@@ -320,6 +327,7 @@
     ichan = nchan & 3;
     linfo ("released cont=%d chan=%d\n", ncont, ichan);
     dma_controllers[ncont].status &= ~(1 << (ichan + 4));
+    DMA_run();
 }
 
 static void channel_run (int ncont, int ichan)
@@ -347,10 +355,13 @@
     ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
 }
 
-void DMA_run (void)
+static QEMUBH *dma_bh;
+
+static void DMA_run (void)
 {
     struct dma_cont *d;
     int icont, ichan;
+    int rearm = 0;
 
     d = dma_controllers;
 
@@ -360,12 +371,22 @@
 
             mask = 1 << ichan;
 
-            if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
+            if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
                 channel_run (icont, ichan);
+                rearm = 1;
+            }
         }
     }
+
+    if (rearm)
+        qemu_bh_schedule_idle(dma_bh);
 }
 
+static void DMA_run_bh(void *unused)
+{
+    DMA_run();
+}
+
 void DMA_register_channel (int nchan,
                            DMA_transfer_handler transfer_handler,
                            void *opaque)
@@ -534,6 +555,9 @@
         qemu_get_8s (f, &r->dack);
         qemu_get_8s (f, &r->eop);
     }
+
+    DMA_run();
+
     return 0;
 }
 
@@ -545,4 +569,6 @@
               high_page_enable ? 0x488 : -1);
     register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
     register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
+
+    dma_bh = qemu_bh_new(DMA_run_bh, NULL);
 }

Modified: trunk/hw/etraxfs_dma.c
===================================================================
--- trunk/hw/etraxfs_dma.c      2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/etraxfs_dma.c      2008-10-31 17:25:56 UTC (rev 5573)
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <sys/time.h>
 #include "hw.h"
+#include "qemu-common.h"
+#include "sysemu.h"
 
 #include "etraxfs_dma.h"
 
@@ -190,6 +192,8 @@
 
        int nr_channels;
        struct fs_dma_channel *channels;
+
+        QEMUBH *bh;
 };
 
 static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg)
@@ -712,11 +716,12 @@
 }
 
 
-static void *etraxfs_dmac;
-void DMA_run(void)
+static void DMA_run(void *opaque)
 {
-       if (etraxfs_dmac)
-               etraxfs_dmac_run(etraxfs_dmac);
+    struct fs_dma_ctrl *etraxfs_dmac = opaque;
+    if (vm_running)
+        etraxfs_dmac_run(etraxfs_dmac);
+    qemu_bh_schedule_idle(etraxfs_dmac->bh);
 }
 
 void *etraxfs_dmac_init(CPUState *env, 
@@ -729,6 +734,9 @@
        if (!ctrl)
                return NULL;
 
+        ctrl->bh = qemu_bh_new(DMA_run, ctrl);
+        qemu_bh_schedule_idle(ctrl->bh);
+
        ctrl->base = base;
        ctrl->env = env;
        ctrl->nr_channels = nr_channels;
@@ -747,8 +755,6 @@
                                              ctrl->channels[i].regmap);
        }
 
-       /* Hax, we only support one DMA controller at a time.  */
-       etraxfs_dmac = ctrl;
        return ctrl;
   err:
        qemu_free(ctrl->channels);

Modified: trunk/hw/integratorcp.c
===================================================================
--- trunk/hw/integratorcp.c     2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/integratorcp.c     2008-10-31 17:25:56 UTC (rev 5573)
@@ -15,10 +15,6 @@
 #include "arm-misc.h"
 #include "net.h"
 
-void DMA_run (void)
-{
-}
-
 typedef struct {
     uint32_t flash_offset;
     uint32_t cm_osc;

Modified: trunk/hw/isa.h
===================================================================
--- trunk/hw/isa.h      2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/isa.h      2008-10-31 17:25:56 UTC (rev 5573)
@@ -19,7 +19,6 @@
 void DMA_hold_DREQ (int nchan);
 void DMA_release_DREQ (int nchan);
 void DMA_schedule(int nchan);
-void DMA_run (void);
 void DMA_init (int high_page_enable);
 void DMA_register_channel (int nchan,
                            DMA_transfer_handler transfer_handler,

Modified: trunk/hw/shix.c
===================================================================
--- trunk/hw/shix.c     2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/shix.c     2008-10-31 17:25:56 UTC (rev 5573)
@@ -35,11 +35,6 @@
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
 
-void DMA_run(void)
-{
-    /* XXXXX */
-}
-
 void irq_info(void)
 {
     /* XXXXX */

Modified: trunk/hw/sun4m.c
===================================================================
--- trunk/hw/sun4m.c    2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/sun4m.c    2008-10-31 17:25:56 UTC (rev 5573)
@@ -164,7 +164,6 @@
 void DMA_hold_DREQ (int nchan) {}
 void DMA_release_DREQ (int nchan) {}
 void DMA_schedule(int nchan) {}
-void DMA_run (void) {}
 void DMA_init (int high_page_enable) {}
 void DMA_register_channel (int nchan,
                            DMA_transfer_handler transfer_handler,

Modified: trunk/hw/sun4u.c
===================================================================
--- trunk/hw/sun4u.c    2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/hw/sun4u.c    2008-10-31 17:25:56 UTC (rev 5573)
@@ -79,7 +79,6 @@
 void DMA_hold_DREQ (int nchan) {}
 void DMA_release_DREQ (int nchan) {}
 void DMA_schedule(int nchan) {}
-void DMA_run (void) {}
 void DMA_init (int high_page_enable) {}
 void DMA_register_channel (int nchan,
                            DMA_transfer_handler transfer_handler,

Modified: trunk/vl.c
===================================================================
--- trunk/vl.c  2008-10-31 17:24:21 UTC (rev 5572)
+++ trunk/vl.c  2008-10-31 17:25:56 UTC (rev 5573)
@@ -7983,8 +7983,6 @@
         if (likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
         qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
                         qemu_get_clock(vm_clock));
-        /* run dma transfers, if any */
-        DMA_run();
     }
 
     /* real time timers */






reply via email to

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