aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes Sorensen <jes@sgi.com>2009-05-25 15:12:49 +0200
committerAvi Kivity <avi@redhat.com>2009-06-07 09:28:11 +0300
commitaaf630a4dd27f8d6e7b4b4c3e44d537a310624f6 (patch)
tree33277ed9dbb9c135ba3e9ec0089275b7a781b26d
parentMake qemu-kvm build and run again on ia64 (diff)
downloadqemu-kvm-aaf630a4dd27f8d6e7b4b4c3e44d537a310624f6.tar.gz
qemu-kvm-aaf630a4dd27f8d6e7b4b4c3e44d537a310624f6.tar.bz2
qemu-kvm-aaf630a4dd27f8d6e7b4b4c3e44d537a310624f6.zip
Flush icache after dma operations for ia64
ia64 system depends on that platform issues snoop cycle to flush icache for memory touched by DMA write operations, but virtual DMA operations is emulated by memcpy, so use explict instrustions to flush the related icache, otherwise, guest may use obsolete icache. Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com> Signed-off-by: Jes Sorensen <jes@sgi.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--cache-utils.h21
-rw-r--r--cutils.c5
-rw-r--r--dma-helpers.c4
-rw-r--r--exec.c7
-rw-r--r--target-ia64/cpu.h1
-rw-r--r--target-ia64/fake-exec.c9
6 files changed, 36 insertions, 11 deletions
diff --git a/cache-utils.h b/cache-utils.h
index b45fde44e..e4f27ef51 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -34,7 +34,28 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
asm volatile ("isync" : : : "memory");
}
+/*
+ * Is this correct for PPC?
+ */
+static inline void dma_flush_range(unsigned long start, unsigned long stop)
+{
+}
+
+#elif defined(__ia64__)
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+ while (start < stop) {
+ asm volatile ("fc %0" :: "r"(start));
+ start += 32;
+ }
+ asm volatile (";;sync.i;;srlz.i;;");
+}
+#define dma_flush_range(start, end) flush_icache_range(start, end)
+#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
#else
+static inline void dma_flush_range(unsigned long start, unsigned long stop)
+{
+}
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
#endif
diff --git a/cutils.c b/cutils.c
index 0623cf70d..6ea0c4962 100644
--- a/cutils.c
+++ b/cutils.c
@@ -164,6 +164,11 @@ void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf)
}
}
+/*
+ * No dma flushing needed here, as the aio code will call dma_bdrv_cb()
+ * on completion as well, which will result in a call to
+ * dma_bdrv_unmap() which will do the flushing ....
+ */
void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count)
{
const uint8_t *p = (const uint8_t *)buf;
diff --git a/dma-helpers.c b/dma-helpers.c
index 712ed897f..d4fc077c0 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -160,6 +160,10 @@ static BlockDriverAIOCB *dma_bdrv_io(
dbs->is_write = is_write;
dbs->bh = NULL;
qemu_iovec_init(&dbs->iov, sg->nsg);
+ /*
+ * DMA flushing is handled in dma_bdrv_cb() calling dma_bdrv_unmap()
+ * so we don't need to do that here.
+ */
dma_bdrv_cb(dbs, 0);
if (!dbs->acb) {
qemu_aio_release(dbs);
diff --git a/exec.c b/exec.c
index c024b8b8e..7c777c25a 100644
--- a/exec.c
+++ b/exec.c
@@ -35,6 +35,7 @@
#include "cpu.h"
#include "exec-all.h"
#include "qemu-common.h"
+#include "cache-utils.h"
#if !defined(TARGET_IA64)
#include "tcg.h"
@@ -3500,6 +3501,8 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len)
{
+ unsigned long flush_len = (unsigned long)access_len;
+
if (buffer != bounce.buffer) {
if (is_write) {
ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
@@ -3517,7 +3520,9 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
}
addr1 += l;
access_len -= l;
- }
+ }
+ dma_flush_range((unsigned long)buffer,
+ (unsigned long)buffer + flush_len);
}
return;
}
diff --git a/target-ia64/cpu.h b/target-ia64/cpu.h
index e002d5617..fb51463d1 100644
--- a/target-ia64/cpu.h
+++ b/target-ia64/cpu.h
@@ -71,7 +71,6 @@ static inline int cpu_mmu_index (CPUState *env)
* These ones really should go to the appropriate tcg header file, if/when
* tcg support is added for ia64.
*/
-void flush_icache_range(unsigned long start, unsigned long stop);
void tcg_dump_info(FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
diff --git a/target-ia64/fake-exec.c b/target-ia64/fake-exec.c
index c11cc3221..8d6ded0a7 100644
--- a/target-ia64/fake-exec.c
+++ b/target-ia64/fake-exec.c
@@ -41,15 +41,6 @@ void tcg_dump_info(FILE *f,
return;
}
-void flush_icache_range(unsigned long start, unsigned long stop)
-{
- while (start < stop) {
- asm volatile ("fc %0" :: "r"(start));
- start += 32;
- }
- asm volatile (";;sync.i;;srlz.i;;");
-}
-
int cpu_restore_state(TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc)