From 7a3148a955e3350720a01f57163ab230b72aca7e Mon Sep 17 00:00:00 2001 From: j_mayer Date: Thu, 5 Apr 2007 07:13:51 +0000 Subject: [PATCH] Preliminary patch for Alpha Linux user mode emulation support. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2600 c046a42c-6fe2-441c-8c8c-71466251a162 --- linux-user/elfload.c | 31 ++++++++++-- linux-user/main.c | 102 ++++++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 36 ++++++++++++++ linux-user/syscall_defs.h | 48 +++++++++++++++++- 4 files changed, 212 insertions(+), 5 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index c0ea5a0125..5caa44eafd 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -313,6 +313,31 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #endif +#ifdef TARGET_ALPHA + +#define ELF_START_MMAP (0x30000000000ULL) + +#define elf_check_arch(x) ( (x) == ELF_ARCH ) + +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_ALPHA + +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +{ + regs->pc = infop->entry; + regs->ps = 8; + regs->usp = infop->start_stack; + regs->unique = infop->start_data; /* ? */ + printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", + regs->unique, infop->start_data); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 8192 + +#endif /* TARGET_ALPHA */ + #ifndef ELF_PLATFORM #define ELF_PLATFORM (NULL) #endif @@ -431,11 +456,11 @@ static void bswap_shdr(struct elf_shdr *shdr) bswaptls(&shdr->sh_entsize); } -static void bswap_sym(Elf32_Sym *sym) +static void bswap_sym(struct elf_sym *sym) { bswap32s(&sym->st_name); - bswap32s(&sym->st_value); - bswap32s(&sym->st_size); + bswaptls(&sym->st_value); + bswaptls(&sym->st_size); bswap16s(&sym->st_shndx); } #endif diff --git a/linux-user/main.c b/linux-user/main.c index 0c5e6b5b43..cad10e646b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1534,6 +1534,96 @@ void cpu_loop(CPUM68KState *env) } #endif /* TARGET_M68K */ +#ifdef TARGET_ALPHA +void cpu_loop (CPUState *env) +{ + int trapnr, ret; + target_siginfo_t info; + + while (1) { + trapnr = cpu_alpha_exec (env); + + switch (trapnr) { + case EXCP_RESET: + fprintf(stderr, "Reset requested. Exit\n"); + exit(1); + break; + case EXCP_MCHK: + fprintf(stderr, "Machine check exception. Exit\n"); + exit(1); + break; + case EXCP_ARITH: + fprintf(stderr, "Arithmetic trap.\n"); + exit(1); + break; + case EXCP_HW_INTERRUPT: + fprintf(stderr, "External interrupt. Exit\n"); + exit(1); + break; + case EXCP_DFAULT: + fprintf(stderr, "MMU data fault\n"); + exit(1); + break; + case EXCP_DTB_MISS_PAL: + fprintf(stderr, "MMU data TLB miss in PALcode\n"); + exit(1); + break; + case EXCP_ITB_MISS: + fprintf(stderr, "MMU instruction TLB miss\n"); + exit(1); + break; + case EXCP_ITB_ACV: + fprintf(stderr, "MMU instruction access violation\n"); + exit(1); + break; + case EXCP_DTB_MISS_NATIVE: + fprintf(stderr, "MMU data TLB miss\n"); + exit(1); + break; + case EXCP_UNALIGN: + fprintf(stderr, "Unaligned access\n"); + exit(1); + break; + case EXCP_OPCDEC: + fprintf(stderr, "Invalid instruction\n"); + exit(1); + break; + case EXCP_FEN: + fprintf(stderr, "Floating-point not allowed\n"); + exit(1); + break; + case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1): + fprintf(stderr, "Call to PALcode\n"); + call_pal(env, (trapnr >> 6) | 0x80); + break; + case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1): + fprintf(stderr, "Priviledged call to PALcode\n"); + exit(1); + break; + case EXCP_DEBUG: + { + int sig; + + sig = gdb_handlesig (env, TARGET_SIGTRAP); + if (sig) + { + info.si_signo = sig; + info.si_errno = 0; + info.si_code = TARGET_TRAP_BRKPT; + queue_signal(info.si_signo, &info); + } + } + break; + default: + printf ("Unhandled trap: 0x%x\n", trapnr); + cpu_dump_state(env, stderr, fprintf, 0); + exit (1); + } + process_pending_signals (env); + } +} +#endif /* TARGET_ALPHA */ + void usage(void) { printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n" @@ -1877,6 +1967,18 @@ int main(int argc, char **argv) } env->pc = regs->pc; } +#elif defined(TARGET_ALPHA) + { + int i; + + for(i = 0; i < 28; i++) { + env->ir[i] = ((target_ulong *)regs)[i]; + } + env->ipr[IPR_USP] = regs->usp; + env->ir[30] = regs->usp; + env->pc = regs->pc; + env->unique = regs->unique; + } #else #error unsupported target CPU #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 33778aaba0..9dc0b09b05 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1765,6 +1765,16 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) newsp = env->gregs[15]; new_env->gregs[15] = newsp; /* XXXXX */ +#elif defined(TARGET_ALPHA) + if (!newsp) + newsp = env->ir[30]; + new_env->ir[30] = newsp; + /* ? */ + { + int i; + for (i = 7; i < 30; i++) + new_env->ir[i] = 0; + } #else #error unsupported target CPU #endif @@ -2067,11 +2077,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, } break; #endif +#ifdef TARGET_NR_creat /* not on alpha */ case TARGET_NR_creat: p = lock_user_string(arg1); ret = get_errno(creat(p, arg2)); unlock_user(p, arg1, 0); break; +#endif case TARGET_NR_link: { void * p2; @@ -2179,7 +2191,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_lseek: ret = get_errno(lseek(arg1, arg2, arg3)); break; +#ifdef TARGET_NR_getxpid + case TARGET_NR_getxpid: +#else case TARGET_NR_getpid: +#endif ret = get_errno(getpid()); break; case TARGET_NR_mount: @@ -2202,6 +2218,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, unlock_user(p, arg1, 0); break; #endif +#ifdef TARGET_NR_stime /* not on alpha */ case TARGET_NR_stime: { time_t host_time; @@ -2209,18 +2226,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(stime(&host_time)); } break; +#endif case TARGET_NR_ptrace: goto unimplemented; +#ifdef TARGET_NR_alarm /* not on alpha */ case TARGET_NR_alarm: ret = alarm(arg1); break; +#endif #ifdef TARGET_NR_oldfstat case TARGET_NR_oldfstat: goto unimplemented; #endif +#ifdef TARGET_NR_pause /* not on alpha */ case TARGET_NR_pause: ret = get_errno(pause()); break; +#endif #ifdef TARGET_NR_utime case TARGET_NR_utime: { @@ -2270,9 +2292,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(access(p, arg2)); unlock_user(p, arg1, 0); break; +#ifdef TARGET_NR_nice /* not on alpha */ case TARGET_NR_nice: ret = get_errno(nice(arg1)); break; +#endif #ifdef TARGET_NR_ftime case TARGET_NR_ftime: goto unimplemented; @@ -2346,11 +2370,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(acct(path(p))); unlock_user(p, arg1, 0); break; +#ifdef TARGET_NR_umount2 /* not on alpha */ case TARGET_NR_umount2: p = lock_user_string(arg1); ret = get_errno(umount2(p, arg2)); unlock_user(p, arg1, 0); break; +#endif #ifdef TARGET_NR_lock case TARGET_NR_lock: goto unimplemented; @@ -2389,9 +2415,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_dup2: ret = get_errno(dup2(arg1, arg2)); break; +#ifdef TARGET_NR_getppid /* not on alpha */ case TARGET_NR_getppid: ret = get_errno(getppid()); break; +#endif case TARGET_NR_getpgrp: ret = get_errno(getpgrp()); break; @@ -2474,6 +2502,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, unlock_user_struct(oact, arg3, 1); } break; +#ifdef TARGET_NR_sgetmask /* not on alpha */ case TARGET_NR_sgetmask: { sigset_t cur_set; @@ -2483,6 +2512,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = target_set; } break; +#endif +#ifdef TARGET_NR_ssetmask /* not on alpha */ case TARGET_NR_ssetmask: { sigset_t set, oset, cur_set; @@ -2495,6 +2526,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = target_set; } break; +#endif #ifdef TARGET_NR_sigprocmask case TARGET_NR_sigprocmask: { @@ -3256,6 +3288,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_afs_syscall: goto unimplemented; #endif +#ifdef TARGET_NR__llseek /* Not on alpha */ case TARGET_NR__llseek: { #if defined (__x86_64__) @@ -3268,6 +3301,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, #endif } break; +#endif case TARGET_NR_getdents: #if TARGET_LONG_SIZE != 4 goto unimplemented; @@ -3431,9 +3465,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_getsid: ret = get_errno(getsid(arg1)); break; +#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ case TARGET_NR_fdatasync: ret = get_errno(fdatasync(arg1)); break; +#endif case TARGET_NR__sysctl: /* We don't implement this, but ENODIR is always a safe return value. */ diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index e33c12bebe..2989bb763a 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -49,7 +49,7 @@ #define TARGET_IOC_TYPEBITS 8 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ - || defined(TARGET_M68K) + || defined(TARGET_M68K) || defined(TARGET_ALPHA) #define TARGET_IOC_SIZEBITS 14 #define TARGET_IOC_DIRBITS 2 @@ -294,7 +294,7 @@ struct target_sigaction; int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact); -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) #if defined(TARGET_SPARC) #define TARGET_SA_NOCLDSTOP 8u @@ -1203,6 +1203,50 @@ struct target_stat64 { int64_t st_blocks; }; + +#elif defined(TARGET_ALPHA) + +struct target_stat { + unsigned int st_dev; + unsigned int st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + target_long st_size; + target_ulong target_st_atime; + target_ulong target_st_mtime; + target_ulong target_st_ctime; + unsigned int st_blksize; + unsigned int st_blocks; + unsigned int st_flags; + unsigned int st_gen; +}; + +struct target_stat64 { + target_ulong st_dev; + target_ulong st_ino; + target_ulong st_rdev; + target_long st_size; + target_ulong st_blocks; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_blksize; + unsigned int st_nlink; + unsigned int __pad0; + + target_ulong target_st_atime; + target_ulong target_st_atime_nsec; + target_ulong target_st_mtime; + target_ulong target_st_mtime_nsec; + target_ulong target_st_ctime; + target_ulong target_st_ctime_nsec; + target_long __unused[3]; +}; + #else #error unsupported CPU #endif