Commit 84409ddbda9b4d8f2d2ad4f580e987800b8e7c4e

Authored by j_mayer
1 parent 9ead1a12

Code provision for x86_64 and PowerPC 64 linux user mode support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2619 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/elfload.c
... ... @@ -44,6 +44,23 @@ static uint32_t get_elf_hwcap(void)
44 44 return global_env->cpuid_features;
45 45 }
46 46  
  47 +#ifdef TARGET_X86_64
  48 +#define ELF_START_MMAP 0x2aaaaab000ULL
  49 +#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
  50 +
  51 +#define ELF_CLASS ELFCLASS64
  52 +#define ELF_DATA ELFDATA2LSB
  53 +#define ELF_ARCH EM_X86_64
  54 +
  55 +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
  56 +{
  57 + regs->rax = 0;
  58 + regs->rsp = infop->start_stack;
  59 + regs->rip = infop->entry;
  60 +}
  61 +
  62 +#else
  63 +
47 64 #define ELF_START_MMAP 0x80000000
48 65  
49 66 /*
... ... @@ -72,6 +89,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
72 89 A value of 0 tells we have no such handler. */
73 90 regs->edx = 0;
74 91 }
  92 +#endif
75 93  
76 94 #define USE_ELF_CORE_DUMP
77 95 #define ELF_EXEC_PAGESIZE 4096
... ... @@ -177,9 +195,20 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
177 195  
178 196 #define ELF_START_MMAP 0x80000000
179 197  
  198 +#ifdef TARGET_PPC64
  199 +
  200 +#define elf_check_arch(x) ( (x) == EM_PPC64 )
  201 +
  202 +#define ELF_CLASS ELFCLASS64
  203 +
  204 +#else
  205 +
180 206 #define elf_check_arch(x) ( (x) == EM_PPC )
181 207  
182 208 #define ELF_CLASS ELFCLASS32
  209 +
  210 +#endif
  211 +
183 212 #ifdef TARGET_WORDS_BIGENDIAN
184 213 #define ELF_DATA ELFDATA2MSB
185 214 #else
... ... @@ -222,9 +251,18 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
222 251 {
223 252 target_ulong pos = infop->start_stack;
224 253 target_ulong tmp;
  254 +#ifdef TARGET_PPC64
  255 + target_ulong entry, toc;
  256 +#endif
225 257  
226 258 _regs->msr = 1 << MSR_PR; /* Set user mode */
227 259 _regs->gpr[1] = infop->start_stack;
  260 +#ifdef TARGET_PPC64
  261 + entry = ldq_raw(infop->entry) + infop->load_addr;
  262 + toc = ldq_raw(infop->entry + 8) + infop->load_addr;
  263 + _regs->gpr[2] = toc;
  264 + infop->entry = entry;
  265 +#endif
228 266 _regs->nip = infop->entry;
229 267 /* Note that isn't exactly what regular kernel does
230 268 * 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,
917 955 unsigned long elf_entry, interp_load_addr = 0;
918 956 int status;
919 957 unsigned long start_code, end_code, end_data;
  958 + unsigned long reloc_func_desc = 0;
920 959 unsigned long elf_stack;
921 960 char passed_fileno[6];
922 961  
... ... @@ -1181,6 +1220,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1181 1220 load_bias += error -
1182 1221 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
1183 1222 load_addr += load_bias;
  1223 + reloc_func_desc = load_bias;
1184 1224 }
1185 1225 }
1186 1226 k = elf_ppnt->p_vaddr;
... ... @@ -1213,6 +1253,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1213 1253 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
1214 1254 &interp_load_addr);
1215 1255 }
  1256 + reloc_func_desc = interp_load_addr;
1216 1257  
1217 1258 close(interpreter_fd);
1218 1259 free(elf_interpreter);
... ...
linux-user/main.c
... ... @@ -194,9 +194,12 @@ void cpu_loop(CPUX86State *env)
194 194 queue_signal(info.si_signo, &info);
195 195 break;
196 196 case EXCP0D_GPF:
  197 +#ifndef TARGET_X86_64
197 198 if (env->eflags & VM_MASK) {
198 199 handle_vm86_fault(env);
199   - } else {
  200 + } else
  201 +#endif
  202 + {
200 203 info.si_signo = SIGSEGV;
201 204 info.si_errno = 0;
202 205 info.si_code = TARGET_SI_KERNEL;
... ... @@ -215,9 +218,12 @@ void cpu_loop(CPUX86State *env)
215 218 queue_signal(info.si_signo, &info);
216 219 break;
217 220 case EXCP00_DIVZ:
  221 +#ifndef TARGET_X86_64
218 222 if (env->eflags & VM_MASK) {
219 223 handle_vm86_trap(env, trapnr);
220   - } else {
  224 + } else
  225 +#endif
  226 + {
221 227 /* division by zero */
222 228 info.si_signo = SIGFPE;
223 229 info.si_errno = 0;
... ... @@ -228,9 +234,12 @@ void cpu_loop(CPUX86State *env)
228 234 break;
229 235 case EXCP01_SSTP:
230 236 case EXCP03_INT3:
  237 +#ifndef TARGET_X86_64
231 238 if (env->eflags & VM_MASK) {
232 239 handle_vm86_trap(env, trapnr);
233   - } else {
  240 + } else
  241 +#endif
  242 + {
234 243 info.si_signo = SIGTRAP;
235 244 info.si_errno = 0;
236 245 if (trapnr == EXCP01_SSTP) {
... ... @@ -245,9 +254,12 @@ void cpu_loop(CPUX86State *env)
245 254 break;
246 255 case EXCP04_INTO:
247 256 case EXCP05_BOUND:
  257 +#ifndef TARGET_X86_64
248 258 if (env->eflags & VM_MASK) {
249 259 handle_vm86_trap(env, trapnr);
250   - } else {
  260 + } else
  261 +#endif
  262 + {
251 263 info.si_signo = SIGSEGV;
252 264 info.si_errno = 0;
253 265 info.si_code = TARGET_SI_KERNEL;
... ... @@ -1807,6 +1819,17 @@ int main(int argc, char **argv)
1807 1819 env->eflags |= IF_MASK;
1808 1820  
1809 1821 /* linux register setup */
  1822 +#if defined(TARGET_X86_64)
  1823 + env->regs[R_EAX] = regs->rax;
  1824 + env->regs[R_EBX] = regs->rbx;
  1825 + env->regs[R_ECX] = regs->rcx;
  1826 + env->regs[R_EDX] = regs->rdx;
  1827 + env->regs[R_ESI] = regs->rsi;
  1828 + env->regs[R_EDI] = regs->rdi;
  1829 + env->regs[R_EBP] = regs->rbp;
  1830 + env->regs[R_ESP] = regs->rsp;
  1831 + env->eip = regs->rip;
  1832 +#else
1810 1833 env->regs[R_EAX] = regs->eax;
1811 1834 env->regs[R_EBX] = regs->ebx;
1812 1835 env->regs[R_ECX] = regs->ecx;
... ... @@ -1816,6 +1839,7 @@ int main(int argc, char **argv)
1816 1839 env->regs[R_EBP] = regs->ebp;
1817 1840 env->regs[R_ESP] = regs->esp;
1818 1841 env->eip = regs->eip;
  1842 +#endif
1819 1843  
1820 1844 /* linux interrupt setup */
1821 1845 env->idt.base = h2g(idt_table);
... ... @@ -1903,6 +1927,9 @@ int main(int argc, char **argv)
1903 1927 if (i != 12 && i != 6 && i != 13)
1904 1928 env->msr[i] = (regs->msr >> i) & 1;
1905 1929 }
  1930 +#if defined(TARGET_PPC64)
  1931 + msr_sf = 1;
  1932 +#endif
1906 1933 env->nip = regs->nip;
1907 1934 for(i = 0; i < 32; i++) {
1908 1935 env->gpr[i] = regs->gpr[i];
... ...
linux-user/qemu.h
... ... @@ -68,7 +68,7 @@ typedef struct TaskState {
68 68 uint32_t heap_limit;
69 69 int swi_errno;
70 70 #endif
71   -#ifdef TARGET_I386
  71 +#if defined(TARGET_I386) && !defined(TARGET_X86_64)
72 72 target_ulong target_v86;
73 73 struct vm86_saved_state vm86_saved_regs;
74 74 struct target_vm86plus_struct vm86plus;
... ...
linux-user/signal.c
... ... @@ -690,7 +690,11 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
690 690 err |= __put_user(frame->retcode, &frame->pretcode);
691 691 /* This is popl %eax ; movl $,%eax ; int $0x80 */
692 692 err |= __put_user(0xb858, (short *)(frame->retcode+0));
  693 +#if defined(TARGET_X86_64)
  694 +#warning "Fix this !"
  695 +#else
693 696 err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
  697 +#endif
694 698 err |= __put_user(0x80cd, (short *)(frame->retcode+6));
695 699 }
696 700  
... ... @@ -2048,7 +2052,7 @@ void process_pending_signals(void *cpu_env)
2048 2052 host_to_target_sigset_internal(&target_old_set, &old_set);
2049 2053  
2050 2054 /* if the CPU is in VM86 mode, we restore the 32 bit values */
2051   -#ifdef TARGET_I386
  2055 +#if defined(TARGET_I386) && !defined(TARGET_X86_64)
2052 2056 {
2053 2057 CPUX86State *env = cpu_env;
2054 2058 if (env->eflags & VM_MASK)
... ...
linux-user/syscall.c
... ... @@ -3250,12 +3250,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
3250 3250 case TARGET_NR_modify_ldt:
3251 3251 ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3));
3252 3252 break;
  3253 +#if !defined(TARGET_X86_64)
3253 3254 case TARGET_NR_vm86old:
3254 3255 goto unimplemented;
3255 3256 case TARGET_NR_vm86:
3256 3257 ret = do_vm86(cpu_env, arg1, arg2);
3257 3258 break;
3258 3259 #endif
  3260 +#endif
3259 3261 case TARGET_NR_adjtimex:
3260 3262 goto unimplemented;
3261 3263 #ifdef TARGET_NR_create_module
... ... @@ -3275,8 +3277,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
3275 3277 case TARGET_NR_fchdir:
3276 3278 ret = get_errno(fchdir(arg1));
3277 3279 break;
  3280 +#ifdef TARGET_NR_bdflush /* not on x86_64 */
3278 3281 case TARGET_NR_bdflush:
3279 3282 goto unimplemented;
  3283 +#endif
3280 3284 #ifdef TARGET_NR_sysfs
3281 3285 case TARGET_NR_sysfs:
3282 3286 goto unimplemented;
... ...