mirror of https://github.com/xemu-project/xemu.git
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
This commit is contained in:
parent
9ead1a1263
commit
84409ddbda
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -3250,11 +3250,13 @@ 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;
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue