ppc64 host support
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
@@ -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
@@ -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; + asmvolatile ("mftb %0\n" :"=r" (t)); +return t; +} + +#elif defined(__powerpc__)static inline uint32_t get_tbl (void ) {
cpu-exec.c +29 -3
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 ) { + asmvolatile ("dcbst 0,%0" : :"r" (p) :"memory" ); + } + asmvolatile ("sync" : : :"memory" ); +for (p = start; p < stop; p +=MIN_CACHE_LINE_SIZE ) { + asmvolatile ("icbi 0,%0" : :"r" (p) :"memory" ); + } +#ifndef __powerpc64__ + asmvolatile ("sync" : : :"memory" ); +#endif + asmvolatile ("isync" : : :"memory" ); +}
ppc64.ld +222 -0
222 lines not on this page · raw message
translate-all.c +13 -2
@@ -31,6 +31,9 @@#include "disas.h" extern int dyngen_code (uint8_t *gen_code_buf, +#ifdef __powerpc64__ + uint64_t *toc_addr_ptr, +#endifuint16_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