Commit 84409ddbda9b4d8f2d2ad4f580e987800b8e7c4e
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
Showing
5 changed files
with
82 additions
and
6 deletions
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; | ... | ... |