Code provision for x86_64 and PowerPC 64 linux user mode support.
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 6 Apr 2007 08:56:50 +0000 (08:56 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 6 Apr 2007 08:56:50 +0000 (08:56 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2619 c046a42c-6fe2-441c-8c8c-71466251a162

linux-user/elfload.c
linux-user/main.c
linux-user/qemu.h
linux-user/signal.c
linux-user/syscall.c

index 5caa44e..1256dba 100644 (file)
@@ -44,6 +44,23 @@ static uint32_t get_elf_hwcap(void)
   return global_env->cpuid_features;
 }
 
+#ifdef TARGET_X86_64
+#define ELF_START_MMAP 0x2aaaaab000ULL
+#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
+
+#define ELF_CLASS      ELFCLASS64
+#define ELF_DATA       ELFDATA2LSB
+#define ELF_ARCH       EM_X86_64
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+    regs->rax = 0;
+    regs->rsp = infop->start_stack;
+    regs->rip = infop->entry;
+}
+
+#else
+
 #define ELF_START_MMAP 0x80000000
 
 /*
@@ -72,6 +89,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
        A value of 0 tells we have no such handler.  */
     regs->edx = 0;
 }
+#endif
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      4096
@@ -177,9 +195,20 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #define ELF_START_MMAP 0x80000000
 
+#ifdef TARGET_PPC64
+
+#define elf_check_arch(x) ( (x) == EM_PPC64 )
+
+#define ELF_CLASS      ELFCLASS64
+
+#else
+
 #define elf_check_arch(x) ( (x) == EM_PPC )
 
 #define ELF_CLASS      ELFCLASS32
+
+#endif
+
 #ifdef TARGET_WORDS_BIGENDIAN
 #define ELF_DATA       ELFDATA2MSB
 #else
@@ -222,9 +251,18 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
 {
     target_ulong pos = infop->start_stack;
     target_ulong tmp;
+#ifdef TARGET_PPC64
+    target_ulong entry, toc;
+#endif
 
     _regs->msr = 1 << MSR_PR; /* Set user mode */
     _regs->gpr[1] = infop->start_stack;
+#ifdef TARGET_PPC64
+    entry = ldq_raw(infop->entry) + infop->load_addr;
+    toc = ldq_raw(infop->entry + 8) + infop->load_addr;
+    _regs->gpr[2] = toc;
+    infop->entry = entry;
+#endif
     _regs->nip = infop->entry;
     /* Note that isn't exactly what regular kernel does
      * but this is what the ABI wants and is needed to allow
@@ -917,6 +955,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     unsigned long elf_entry, interp_load_addr = 0;
     int status;
     unsigned long start_code, end_code, end_data;
+    unsigned long reloc_func_desc = 0;
     unsigned long elf_stack;
     char passed_fileno[6];
 
@@ -1181,6 +1220,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
+                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1213,6 +1253,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
            elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
                                            &interp_load_addr);
        }
+        reloc_func_desc = interp_load_addr;
 
        close(interpreter_fd);
        free(elf_interpreter);
index cad10e6..74798c7 100644 (file)
@@ -194,9 +194,12 @@ void cpu_loop(CPUX86State *env)
             queue_signal(info.si_signo, &info);
             break;
         case EXCP0D_GPF:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_fault(env);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SI_KERNEL;
@@ -215,9 +218,12 @@ void cpu_loop(CPUX86State *env)
             queue_signal(info.si_signo, &info);
             break;
         case EXCP00_DIVZ:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 /* division by zero */
                 info.si_signo = SIGFPE;
                 info.si_errno = 0;
@@ -228,9 +234,12 @@ void cpu_loop(CPUX86State *env)
             break;
         case EXCP01_SSTP:
         case EXCP03_INT3:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGTRAP;
                 info.si_errno = 0;
                 if (trapnr == EXCP01_SSTP) {
@@ -245,9 +254,12 @@ void cpu_loop(CPUX86State *env)
             break;
         case EXCP04_INTO:
         case EXCP05_BOUND:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SI_KERNEL;
@@ -1807,6 +1819,17 @@ int main(int argc, char **argv)
     env->eflags |= IF_MASK;
     
     /* linux register setup */
+#if defined(TARGET_X86_64)
+    env->regs[R_EAX] = regs->rax;
+    env->regs[R_EBX] = regs->rbx;
+    env->regs[R_ECX] = regs->rcx;
+    env->regs[R_EDX] = regs->rdx;
+    env->regs[R_ESI] = regs->rsi;
+    env->regs[R_EDI] = regs->rdi;
+    env->regs[R_EBP] = regs->rbp;
+    env->regs[R_ESP] = regs->rsp;
+    env->eip = regs->rip;
+#else
     env->regs[R_EAX] = regs->eax;
     env->regs[R_EBX] = regs->ebx;
     env->regs[R_ECX] = regs->ecx;
@@ -1816,6 +1839,7 @@ int main(int argc, char **argv)
     env->regs[R_EBP] = regs->ebp;
     env->regs[R_ESP] = regs->esp;
     env->eip = regs->eip;
+#endif
 
     /* linux interrupt setup */
     env->idt.base = h2g(idt_table);
@@ -1903,6 +1927,9 @@ int main(int argc, char **argv)
             if (i != 12 && i != 6 && i != 13)
                 env->msr[i] = (regs->msr >> i) & 1;
         }
+#if defined(TARGET_PPC64)
+        msr_sf = 1;
+#endif
         env->nip = regs->nip;
         for(i = 0; i < 32; i++) {
             env->gpr[i] = regs->gpr[i];
index f894dde..31e29da 100644 (file)
@@ -68,7 +68,7 @@ typedef struct TaskState {
     uint32_t heap_limit;
     int swi_errno;
 #endif
-#ifdef TARGET_I386
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
     target_ulong target_v86;
     struct vm86_saved_state vm86_saved_regs;
     struct target_vm86plus_struct vm86plus;
index 1e29c2c..5a99e61 100644 (file)
@@ -690,7 +690,11 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
                err |= __put_user(frame->retcode, &frame->pretcode);
                /* This is popl %eax ; movl $,%eax ; int $0x80 */
                err |= __put_user(0xb858, (short *)(frame->retcode+0));
+#if defined(TARGET_X86_64)
+#warning "Fix this !"
+#else
                err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
+#endif
                err |= __put_user(0x80cd, (short *)(frame->retcode+6));
        }
 
@@ -2048,7 +2052,7 @@ void process_pending_signals(void *cpu_env)
         host_to_target_sigset_internal(&target_old_set, &old_set);
 
         /* if the CPU is in VM86 mode, we restore the 32 bit values */
-#ifdef TARGET_I386
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
         {
             CPUX86State *env = cpu_env;
             if (env->eflags & VM_MASK)
index 9dc0b09..7ab506d 100644 (file)
@@ -3250,12 +3250,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_modify_ldt:
         ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3));
         break;
+#if !defined(TARGET_X86_64)
     case TARGET_NR_vm86old:
         goto unimplemented;
     case TARGET_NR_vm86:
         ret = do_vm86(cpu_env, arg1, arg2);
         break;
 #endif
+#endif
     case TARGET_NR_adjtimex:
         goto unimplemented;
 #ifdef TARGET_NR_create_module
@@ -3275,8 +3277,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_fchdir:
         ret = get_errno(fchdir(arg1));
         break;
+#ifdef TARGET_NR_bdflush /* not on x86_64 */
     case TARGET_NR_bdflush:
         goto unimplemented;
+#endif
 #ifdef TARGET_NR_sysfs
     case TARGET_NR_sysfs:
         goto unimplemented;