OSDN Git Service

target-ppc: Support little-endian PPC64 in user mode.
authorDoug Kwan <dougkwan@google.com>
Thu, 29 May 2014 14:12:19 +0000 (09:12 -0500)
committerAlexander Graf <agraf@suse.de>
Mon, 16 Jun 2014 11:24:40 +0000 (13:24 +0200)
Look at ELF header to determine ABI version on PPC64.  This is required
for executing the first instruction correctly.  Also print correct machine
name in uname() system call.

Signed-off-by: Doug Kwan <dougkwan@google.com>
Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
include/elf.h
linux-user/elfload.c
linux-user/ppc/syscall.h

index 1599ab2..e88d52f 100644 (file)
@@ -561,6 +561,11 @@ typedef struct {
 #define SHF_ALPHA_GPREL                0x10000000
 
 
+/* PowerPC specific definitions.  */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_PPC64_ABI           0x3
+
 /* PowerPC relocations defined by the ABIs */
 #define R_PPC_NONE             0
 #define R_PPC_ADDR32           1       /* 32bit absolute address */
index 68b9793..d08fc80 100644 (file)
@@ -784,12 +784,18 @@ static uint32_t get_elf_hwcap(void)
         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
     } while (0)
 
+static inline uint32_t get_ppc64_abi(struct image_info *infop);
+
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
     _regs->gpr[1] = infop->start_stack;
 #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
-    _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias;
-    infop->entry = ldq_raw(infop->entry) + infop->load_bias;
+    if (get_ppc64_abi(infop) < 2) {
+        _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias;
+        infop->entry = ldq_raw(infop->entry) + infop->load_bias;
+    } else {
+        _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */
+    }
 #endif
     _regs->nip = infop->entry;
 }
@@ -1159,6 +1165,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #include "elf.h"
 
+#ifdef TARGET_PPC
+static inline uint32_t get_ppc64_abi(struct image_info *infop)
+{
+  return infop->elf_flags & EF_PPC64_ABI;
+}
+#endif
+
 struct exec
 {
     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
index 6514c63..db92bbe 100644 (file)
@@ -58,8 +58,12 @@ struct target_revectored_struct {
  */
 
 #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#ifdef TARGET_WORDS_BIGENDIAN
 #define UNAME_MACHINE "ppc64"
 #else
+#define UNAME_MACHINE "ppc64le"
+#endif
+#else
 #define UNAME_MACHINE "ppc"
 #endif
 #define UNAME_MINIMUM_RELEASE "2.6.32"