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:
j_mayer 2007-04-06 08:56:50 +00:00
parent 9ead1a1263
commit 84409ddbda
5 changed files with 82 additions and 6 deletions

View 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);

View 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];

View 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;

View 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)

View File

@ -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;