Skip to contentSkip to conversation

ppc64 host support

PATCH New Heikki Lindholm 1 participant 1 message Aug 3, 2006 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ppc64 host support

A sent a patch some months ago for adding ppc64 host support on Linux. This one's pretty much the same, though updated to apply to the current CVS qemu. Only i386 target tested and working partially.

-- Heikki Lindholm

configure +9 -3
diff -Nru qemu/configure qemu-devel-ppc64/configure
@@ -42,9 +42,12 @@
   alpha)
     cpu="alpha"
   ;;
-  "Power Macintosh"|ppc|ppc64)
+  "Power Macintosh"|ppc)
     cpu="powerpc"
   ;;
+  ppc64)
+    cpu="powerpc64"
+  ;;
   mips)
     cpu="mips"
   ;;
@@ -401,7 +404,7 @@
 else
 
 # if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
+if test "$cpu" = "powerpc" -o "$cpu" = "powerpc64" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
     bigendian="yes"
 fi
 
@@ -409,7 +412,7 @@
 
 # host long bits test
 hostlongbits="32"
-if test "$cpu" = "sparc64" -o "$cpu" = "ia64" -o "$cpu" = "x86_64" -o "$cpu" = "alpha"; then
+if test "$cpu" = "sparc64" -o "$cpu" = "ia64" -o "$cpu" = "x86_64" -o "$cpu" = "alpha" -o "$cpu" = "powerpc64"; then
     hostlongbits="64"
 fi
 
@@ -611,6 +614,9 @@
 elif test "$cpu" = "powerpc" ; then
   echo "ARCH=ppc" >> $config_mak
   echo "#define HOST_PPC 1" >> $config_h
+elif test "$cpu" = "powerpc64" ; then
+  echo "ARCH=ppc64" >> $config_mak
+  echo "#define HOST_PPC64 1" >> $config_h
 elif test "$cpu" = "mips" ; then
   echo "ARCH=mips" >> $config_mak
   echo "#define HOST_MIPS 1" >> $config_h
cpu-all.h +9 -1
diff -Nru qemu/cpu-all.h qemu-devel-ppc64/cpu-all.h
@@ -902,8 +902,16 @@
 
 /*******************************************/
 /* host CPU ticks (if available) */
+#if defined(__powerpc64__)
 
-#if defined(__powerpc__)
+static inline int64_t cpu_get_real_ticks(void)
+{
+    int64_t t;
+    asm volatile("mftb %0\n" : "=r" (t));
+    return t;
+}
+
+#elif defined(__powerpc__)
 
 static inline uint32_t get_tbl(void) 
 {
cpu-exec.c +29 -3
diff -Nru qemu/cpu-exec.c qemu-devel-ppc64/cpu-exec.c
@@ -83,7 +83,10 @@
     unsigned int h;
     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
     uint8_t *tc_ptr;
-    
+#ifdef __powerpc64__
+    long toc_addr;
+#endif
+
     spin_lock(&tb_lock);
 
     tb_invalidated_flag = 0;
@@ -132,9 +135,16 @@
     tb->tc_ptr = tc_ptr;
     tb->cs_base = cs_base;
     tb->flags = flags;
-    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
+    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE,
+#ifdef __powerpc64__
+                 &toc_addr, 
+#endif
+                 &code_gen_size);
     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
-    
+#ifdef __powerpc64__
+    tb->toc_addr = toc_addr;
+#endif
+
     /* check next page if needed */
     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
     phys_page2 = -1;
@@ -261,6 +271,9 @@
     int saved_i7, tmp_T0;
 #endif
     int ret, interrupt_request;
+#ifdef __powerpc64__
+    unsigned long toc_addr;
+#endif
     void (*gen_func)(void);
     TranslationBlock *tb;
     uint8_t *tc_ptr;
@@ -667,6 +680,9 @@
                 }
                 }
                 tc_ptr = tb->tc_ptr;
+#ifdef __powerpc64__
+                toc_addr = tb->toc_addr;
+#endif
                 env->current_tb = tb;
                 /* execute the generated code */
                 gen_func = (void *)tc_ptr;
@@ -759,6 +775,16 @@
             );
     }
 }
+#elif defined(__powerpc64__)
+                struct fdesc {
+                    uint64_t entry;
+                    uint64_t toc_base;
+                    uint64_t env_ptr;
+                } fp;
+                fp.entry = (uint64_t)tc_ptr;
+                fp.toc_base = toc_addr;
+                fp.env_ptr = 0;
+                (*(void (*)(void))&fp)();
 #elif defined(__ia64)
 		struct fptr {
 			void *ip;
dyngen.c +173 -6

339 lines not on this page · raw message

dyngen-exec.h +2 -2
diff -Nru qemu/dyngen-exec.h qemu-devel-ppc64/dyngen-exec.h
@@ -38,7 +38,7 @@
 // Linux/Sparc64 defines uint64_t
 #if !(defined (__sparc_v9__) && defined(__linux__))
 /* XXX may be done for all 64 bits targets ? */
-#if defined (__x86_64__) || defined(__ia64)
+#if defined (__x86_64__) || defined(__ia64) || defined(__powerpc64__)
 typedef unsigned long uint64_t;
 #else
 typedef unsigned long long uint64_t;
@@ -55,7 +55,7 @@
 typedef signed int int32_t;
 // Linux/Sparc64 defines int64_t
 #if !(defined (__sparc_v9__) && defined(__linux__))
-#if defined (__x86_64__) || defined(__ia64)
+#if defined (__x86_64__) || defined(__ia64) || defined(__powerpc64__)
 typedef signed long int64_t;
 #else
 typedef signed long long int64_t;
dyngen.h +136 -20

168 lines not on this page · raw message

elf.h +121 -0

127 lines not on this page · raw message

exec-all.h +81 -7

145 lines not on this page · raw message

exec.c +10 -2
diff -Nru qemu/exec.c qemu-devel-ppc64/exec.c
@@ -450,7 +450,11 @@
    another TB */
 static inline void tb_reset_jump(TranslationBlock *tb, int n)
 {
-    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
+    tb_set_jmp_target(tb, n,
+#ifdef __powerpc64__
+                      tb->toc_addr,
+#endif
+                      (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
 }
 
 static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr)
@@ -591,7 +595,11 @@
     tb->cs_base = cs_base;
     tb->flags = flags;
     tb->cflags = cflags;
-    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
+    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE,
+#ifdef __powerpc64__
+                 &tb->toc_addr,
+#endif
+                 &code_gen_size);
     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
     
     /* check next page if needed */
linux-user/elfload.c +12 -0
diff -Nru qemu/linux-user/elfload.c qemu-devel-ppc64/linux-user/elfload.c
@@ -12,6 +12,18 @@
 #include "qemu.h"
 #include "disas.h"
 
+#ifdef __powerpc64__
+#undef elf_check_arch
+#undef ELF_CLASS
+#undef ELF_DATA
+#undef ELF_ARCH
+#undef ELF_PLAT_INIT
+#undef ELF_PLATFORM
+#undef ELF_HWCAP
+#undef R_PPC_NUM
+#undef ARCH_DLINFO
+#endif
+
 /* this flag is uneffective under linux too, should be deleted */
 #ifndef MAP_DENYWRITE
 #define MAP_DENYWRITE 0
linux-user/mmap.c +2 -2
diff -Nru qemu/linux-user/mmap.c qemu-devel-ppc64/linux-user/mmap.c
@@ -157,7 +157,7 @@
     target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
     long host_start;
 #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
-    defined(__ia64)
+    defined(__ia64) || defined(__powerpc64__)
     static target_ulong last_start = 0x40000000;
 #elif defined(__CYGWIN__)
     /* Cygwin doesn't have a whole lot of address space.  */
@@ -202,7 +202,7 @@
 
     if (!(flags & MAP_FIXED)) {
 #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
-    defined(__ia64) || defined(__CYGWIN__)
+    defined(__ia64) || defined(__powerpc64__) || defined(__CYGWIN__)
         /* tell the kenel to search at the same place as i386 */
         if (real_start == 0) {
             real_start = last_start;
Makefile.target +6 -0
diff -Nru qemu/Makefile.target qemu-devel-ppc64/Makefile.target
@@ -101,6 +101,12 @@
 LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
 endif
 
+ifeq ($(ARCH),ppc64)
+CFLAGS+= -D__powerpc__ -D__powerpc64__
+OP_CFLAGS=$(CFLAGS)
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc64.ld
+endif
+
 ifeq ($(ARCH),s390)
 OP_CFLAGS=$(CFLAGS)
 LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
ppc_icache.h +25 -0
diff -Nru qemu/ppc_icache.h qemu-devel-ppc64/ppc_icache.h
@@ -0,0 +1,25 @@
+#ifdef __powerpc64__
+#define MIN_CACHE_LINE_SIZE 0x80
+#else
+#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
+#endif
+
+static void inline flush_icache_range(unsigned long start, unsigned long stop)
+{
+    unsigned long p;
+
+    start &= ~(MIN_CACHE_LINE_SIZE - 1);
+    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
+    
+    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
+        asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
+    }
+    asm volatile ("sync" : : : "memory");
+    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
+        asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
+    }
+#ifndef __powerpc64__
+    asm volatile ("sync" : : : "memory");
+#endif
+    asm volatile ("isync" : : : "memory");
+}
ppc64.ld +222 -0

222 lines not on this page · raw message

translate-all.c +13 -2
diff -Nru qemu/translate-all.c qemu-devel-ppc64/translate-all.c
@@ -31,6 +31,9 @@
 #include "disas.h"
 
 extern int dyngen_code(uint8_t *gen_code_buf,
+#ifdef __powerpc64__
+                       uint64_t *toc_addr_ptr,
+#endif
                        uint16_t *label_offsets, uint16_t *jmp_offsets,
                        const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
 
@@ -139,7 +142,11 @@
    code).
 */
 int cpu_gen_code(CPUState *env, TranslationBlock *tb,
-                 int max_code_size, int *gen_code_size_ptr)
+                 int max_code_size, 
+#ifdef __powerpc64__
+                 uint64_t *toc_addr_ptr,
+#endif
+                 int *gen_code_size_ptr)
 {
     uint8_t *gen_code_buf;
     int gen_code_size;
@@ -165,7 +172,11 @@
 #endif
         dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
 
-        gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
+        gen_code_size = dyngen_code(gen_code_buf,
+#ifdef __powerpc64__
+                                    toc_addr_ptr,
+#endif
+                                    tb->tb_next_offset,
 #ifdef USE_DIRECT_JUMP
                                     tb->tb_jmp_offset,
 #else