commit 7484a0768297c67207ea9dcab51259c15ddaf94c Author: Stacey Son Date: Tue Oct 2 11:29:35 2012 -0500 Add mips, mipsel, mips64 bsd user diff --git a/Makefile b/Makefile index 8c26738..55e151e 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,8 @@ CLANG_CFLAGS_AS+= -no-integrated-as .if ${PORT_OPTIONS:MX86_TARGETS} .if ${PORT_OPTIONS:MBSD_USER} -CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,armeb-bsd-user +#CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user +CONFIGURE_ARGS+= --target-list=arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user .else CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu .endif @@ -106,6 +107,8 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC} --enable-docs \ --disable-linux-user --disable-linux-aio \ --disable-kvm --disable-xen \ --smbd=${LOCALBASE}/sbin/smbd \ + --enable-debug \ + --enable-debug-info \ --extra-cflags=-I${WRKSRC}\ -I${LOCALBASE}/include\ -DPREFIX=\\\"${PREFIX}\\\" .if empty(PORT_OPTIONS:MSDL) diff --git a/work/qemu-1.2.0/bsd-user/bsdload.c b/work/qemu-1.2.0/bsd-user/bsdload.c index 2abc713..768a6b0 100644 --- a/work/qemu-1.2.0/bsd-user/bsdload.c +++ b/work/qemu-1.2.0/bsd-user/bsdload.c @@ -53,7 +53,7 @@ static int count(char ** vec) return(i); } -static int prepare_binprm(struct linux_binprm *bprm) +static int prepare_binprm(struct bsd_binprm *bprm) { struct stat st; int mode; @@ -155,33 +155,33 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, } int loader_exec(const char * filename, char ** argv, char ** envp, - struct target_pt_regs * regs, struct image_info *infop) + struct target_pt_regs * regs, struct image_info *infop, + struct bsd_binprm *bprm) { - struct linux_binprm bprm; int retval; int i; - bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); + bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); for (i=0 ; ipage[i] = NULL; retval = open(filename, O_RDONLY); if (retval < 0) return retval; - bprm.fd = retval; - bprm.filename = (char *)filename; - bprm.argc = count(argv); - bprm.argv = argv; - bprm.envc = count(envp); - bprm.envp = envp; + bprm->fd = retval; + bprm->filename = (char *)filename; + bprm->argc = count(argv); + bprm->argv = argv; + bprm->envc = count(envp); + bprm->envp = envp; - retval = prepare_binprm(&bprm); + retval = prepare_binprm(bprm); if(retval>=0) { - if (bprm.buf[0] == 0x7f - && bprm.buf[1] == 'E' - && bprm.buf[2] == 'L' - && bprm.buf[3] == 'F') { - retval = load_elf_binary(&bprm,regs,infop); + if (bprm->buf[0] == 0x7f + && bprm->buf[1] == 'E' + && bprm->buf[2] == 'L' + && bprm->buf[3] == 'F') { + retval = load_elf_binary(bprm,regs,infop); } else { fprintf(stderr, "Unknown binary format\n"); return -1; @@ -196,7 +196,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, /* Something went wrong, return the inode and free the argument pages*/ for (i=0 ; ipage[i]); } return(retval); } diff --git a/work/qemu-1.2.0/bsd-user/elfload.c b/work/qemu-1.2.0/bsd-user/elfload.c index 993dcf7..08bd8cf 100644 --- a/work/qemu-1.2.0/bsd-user/elfload.c +++ b/work/qemu-1.2.0/bsd-user/elfload.c @@ -378,13 +378,14 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * #ifdef TARGET_MIPS -#define ELF_START_MMAP 0x80000000 #define elf_check_arch(x) ( (x) == EM_MIPS ) -#ifdef TARGET_MIPS64 +#if defined(TARGET_MIPS64) +#define ELF_START_MMAP 0x2aaaaab000ULL #define ELF_CLASS ELFCLASS64 #else +#define ELF_START_MMAP 0x80000000 #define ELF_CLASS ELFCLASS32 #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -396,9 +397,10 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { + regs->cp0_status = 2 << CP0St_KSU; - regs->cp0_epc = infop->entry; - regs->regs[29] = infop->start_stack; + regs->regs[25] = regs->cp0_epc = infop->entry; /* t9 = pc = entry */ + regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0 = sp = start_stack */ } #define USE_ELF_CORE_DUMP @@ -576,30 +578,38 @@ static void bswap_ehdr(struct elfhdr *ehdr) bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ } -static void bswap_phdr(struct elf_phdr *phdr) +static void bswap_phdr(struct elf_phdr *phdr, int phnum) { - bswap32s(&phdr->p_type); /* Segment type */ - bswaptls(&phdr->p_offset); /* Segment file offset */ - bswaptls(&phdr->p_vaddr); /* Segment virtual address */ - bswaptls(&phdr->p_paddr); /* Segment physical address */ - bswaptls(&phdr->p_filesz); /* Segment size in file */ - bswaptls(&phdr->p_memsz); /* Segment size in memory */ - bswap32s(&phdr->p_flags); /* Segment flags */ - bswaptls(&phdr->p_align); /* Segment alignment */ + int i; + + for (i = 0; i < phnum; ++i, ++phdr) { + bswap32s(&phdr->p_type); /* Segment type */ + bswap32s(&phdr->p_flags); /* Segment flags */ + bswaptls(&phdr->p_offset); /* Segment file offset */ + bswaptls(&phdr->p_vaddr); /* Segment virtual address */ + bswaptls(&phdr->p_paddr); /* Segment physical address */ + bswaptls(&phdr->p_filesz); /* Segment size in file */ + bswaptls(&phdr->p_memsz); /* Segment size in memory */ + bswaptls(&phdr->p_align); /* Segment alignment */ + } } -static void bswap_shdr(struct elf_shdr *shdr) +static void bswap_shdr(struct elf_shdr *shdr, int shnum) { - bswap32s(&shdr->sh_name); - bswap32s(&shdr->sh_type); - bswaptls(&shdr->sh_flags); - bswaptls(&shdr->sh_addr); - bswaptls(&shdr->sh_offset); - bswaptls(&shdr->sh_size); - bswap32s(&shdr->sh_link); - bswap32s(&shdr->sh_info); - bswaptls(&shdr->sh_addralign); - bswaptls(&shdr->sh_entsize); + int i; + + for (i = 0; i < shnum; ++i, ++shdr) { + bswap32s(&shdr->sh_name); + bswap32s(&shdr->sh_type); + bswaptls(&shdr->sh_flags); + bswaptls(&shdr->sh_addr); + bswaptls(&shdr->sh_offset); + bswaptls(&shdr->sh_size); + bswap32s(&shdr->sh_link); + bswap32s(&shdr->sh_info); + bswaptls(&shdr->sh_addralign); + bswaptls(&shdr->sh_entsize); + } } static void bswap_sym(struct elf_sym *sym) @@ -609,7 +619,14 @@ static void bswap_sym(struct elf_sym *sym) bswaptls(&sym->st_size); bswap16s(&sym->st_shndx); } -#endif + +#else /* ! BSWAP_NEEDED */ + +static inline void bswap_ehdr(struct elfhdr *ehdr) { } +static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { } +static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { } +static inline void bswap_sym(struct elf_sym *sym) { } +#endif /* ! BSWAP_NEEDED */ /* * 'copy_elf_strings()' copies argument/envelope strings from user @@ -666,7 +683,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, return p; } -static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, +static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm, struct image_info *info) { abi_ulong stack_base, size, error; @@ -856,9 +873,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, last_bss = 0; error = 0; -#ifdef BSWAP_NEEDED bswap_ehdr(interp_elf_ex); -#endif /* First of all, some simple consistency checks */ if ((interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) || @@ -899,12 +914,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, free (elf_phdata); return retval; } -#ifdef BSWAP_NEEDED - eppnt = elf_phdata; - for (i=0; ie_phnum; i++, eppnt++) { - bswap_phdr(eppnt); - } -#endif + bswap_phdr(elf_phdata, interp_elf_ex->e_phnum); if (interp_elf_ex->e_type == ET_DYN) { /* in order to avoid hardcoding the interpreter load @@ -1049,9 +1059,7 @@ static void load_symbols(struct elfhdr *hdr, int fd) for (i = 0; i < hdr->e_shnum; i++) { if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) return; -#ifdef BSWAP_NEEDED - bswap_shdr(&sechdr); -#endif + bswap_shdr(&sechdr, 1); if (sechdr.sh_type == SHT_SYMTAB) { symtab = sechdr; lseek(fd, hdr->e_shoff @@ -1059,9 +1067,7 @@ static void load_symbols(struct elfhdr *hdr, int fd) if (read(fd, &strtab, sizeof(strtab)) != sizeof(strtab)) return; -#ifdef BSWAP_NEEDED - bswap_shdr(&strtab); -#endif + bswap_shdr(&strtab, 1); goto found; } } @@ -1094,9 +1100,7 @@ static void load_symbols(struct elfhdr *hdr, int fd) i = 0; while (i < nsyms) { -#ifdef BSWAP_NEEDED bswap_sym(syms + i); -#endif // Throw away entries which we do not need. if (syms[i].st_shndx == SHN_UNDEF || syms[i].st_shndx >= SHN_LORESERVE || @@ -1148,7 +1152,7 @@ static void load_symbols(struct elfhdr *hdr, int fd) syminfos = s; } -int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, +int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs, struct image_info * info) { struct elfhdr elf_ex; @@ -1178,9 +1182,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, load_addr = 0; load_bias = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ -#ifdef BSWAP_NEEDED bswap_ehdr(&elf_ex); -#endif /* First of all, some simple consistency checks */ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || @@ -1214,12 +1216,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, return -errno; } -#ifdef BSWAP_NEEDED - elf_ppnt = elf_phdata; - for (i=0; ip_vaddr); + load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); } error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), @@ -1541,12 +1538,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, padzero(elf_bss, elf_brk); #if 0 - printf("(start_brk) %x\n" , info->start_brk); - printf("(end_code) %x\n" , info->end_code); - printf("(start_code) %x\n" , info->start_code); - printf("(end_data) %x\n" , info->end_data); - printf("(start_stack) %x\n" , info->start_stack); - printf("(brk) %x\n" , info->brk); + printf("(start_brk) 0x" TARGET_FMT_lx "\n" , info->start_brk); + printf("(end_code) 0x" TARGET_FMT_lx "\n" , info->end_code); + printf("(start_code) 0x" TARGET_FMT_lx "\n" , info->start_code); + printf("(start_data) 0x" TARGET_FMT_lx "\n" , info->start_data); + printf("(end_data) 0x" TARGET_FMT_lx "\n" , info->end_data); + printf("(start_stack) 0x" TARGET_FMT_lx "\n" , info->start_stack); + printf("(brk) 0x" TARGET_FMT_lx "\n" , info->brk); #endif if ( info->personality == PER_SVR4 ) @@ -1561,6 +1559,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, info->entry = elf_entry; +#ifdef USE_ELF_CORE_DUMP + /* bprm->core_dump = &elf_core_dump; */ + bprm->core_dump = NULL; +#endif + return 0; } diff --git a/work/qemu-1.2.0/bsd-user/main.c b/work/qemu-1.2.0/bsd-user/main.c index b4e42f3..13c1387 100644 --- a/work/qemu-1.2.0/bsd-user/main.c +++ b/work/qemu-1.2.0/bsd-user/main.c @@ -642,6 +642,244 @@ void cpu_loop(CPUARMState *env) #endif +#if defined(TARGET_MIPS) || defined(TARGET_MIPS64) + +/* + * From sys/mips/mips/trap.c syscalls have the following stored away in the + * registers: + * + * v0(2): if either SYS___syscall (198) or SYS_syscall (0) then indirect syscall + * otherwise it is a direct syscall. + * + * If direct syscall: + * + * MIPS MIPS64 + * v0(2): v0(2) syscall # + * a0(4): a0(4) arg0 + * a1(5): a1(5) arg1 + * a2(6): a2(6) arg2 + * a3(7): a3(7) arg3 + * t4(12): a4(8) arg4 + * t5(13): a5(9) arg5 + * t6(14): a6(10) arg6 + * t7(15): a7(11) arg7 + * + * If indirect syscall: + * + * MIPS MIPS64 + * a0(4): a0(4) syscall # + * a1(5): a1(5) arg0 + * a2(6): a2(6) arg1 + * a3(7): a3(7) arg2 + * t4(12): a4(8) arg3 + * t5(13): a5(9) arg4 + * t6(14): a6(10) arg5 + * t7(15): a7(11) arg6 + * + */ + +#include /* For SYS_[__]syscall, SYS_MAXSYSCALL */ + +static int do_store_exclusive(CPUMIPSState *env) +{ + target_ulong addr; + target_ulong page_addr; + target_ulong val; + int flags; + int segv = 0; + int reg; + int d; + + addr = env->lladdr; + page_addr = addr & TARGET_PAGE_MASK; + start_exclusive(); + mmap_lock(); + flags = page_get_flags(page_addr); + if ((flags & PAGE_READ) == 0) { + segv = 1; + } else { + reg = env->llreg & 0x1f; + d = (env->llreg & 0x20) != 0; + if (d) { + segv = get_user_s64(val, addr); + } else { + segv = get_user_s32(val, addr); + } + if (!segv) { + if (val != env->llval) { + env->active_tc.gpr[reg] = 0; + } else { + if (d) { + segv = + put_user_u64(env->llnewval, addr); + } else { + segv = + put_user_u32(env->llnewval, addr); + } + if (!segv) { + env->active_tc.gpr[reg] = 1; + } + } + } + } + env->lladdr = -1; + if (!segv) { + env->active_tc.PC += 4; + } + mmap_unlock(); + end_exclusive(); + return (segv); +} + +void cpu_loop(CPUMIPSState *env) +{ + target_siginfo_t info; + int trapnr; + abi_long ret; + unsigned int syscall_num; + + for(;;) { + cpu_exec_start(env); + trapnr = cpu_mips_exec(env); + cpu_exec_end(env); + switch(trapnr) { + case EXCP_SYSCALL: /* syscall exception */ + syscall_num = env->active_tc.gpr[2]; /* v0 */ + env->active_tc.PC += 4; + if (syscall_num >= SYS_MAXSYSCALL) { + ret = -TARGET_ENOSYS; + } else { + if (SYS_syscall == syscall_num || + SYS___syscall == syscall_num) { +#if defined(TARGET_MIPS64) + ret = do_freebsd_syscall(env, + env->active_tc.gpr[4],/* syscall #*/ + env->active_tc.gpr[5], /* arg0 */ + env->active_tc.gpr[6], /* arg1 */ + env->active_tc.gpr[7], /* arg2 */ + env->active_tc.gpr[8], /* arg3 */ + env->active_tc.gpr[9], /* arg4 */ + env->active_tc.gpr[10],/* arg5 */ + env->active_tc.gpr[11],/* arg6 */ + 0 /* no arg 7 */); + } else { + ret = do_freebsd_syscall(env, + syscall_num, + env->active_tc.gpr[4], + env->active_tc.gpr[5], + env->active_tc.gpr[6], + env->active_tc.gpr[7], + env->active_tc.gpr[8], + env->active_tc.gpr[9], + env->active_tc.gpr[10], + env->active_tc.gpr[11] + ); + +#else /* ! TARGET_MIPS64 */ + /* indirect syscall */ + ret = do_freebsd_syscall(env, + env->active_tc.gpr[4],/* syscall #*/ + env->active_tc.gpr[5], /* a1/arg0 */ + env->active_tc.gpr[6], /* a2/arg1 */ + env->active_tc.gpr[7], /* a3/arg2 */ + env->active_tc.gpr[12],/* t4/arg3 */ + env->active_tc.gpr[13],/* t5/arg4 */ + env->active_tc.gpr[14],/* t6/arg5 */ + env->active_tc.gpr[15],/* t7/arg6 */ + 0 /* no arg7 */ ); + } else { + /* direct syscall */ + ret = do_freebsd_syscall(env, + syscall_num, + env->active_tc.gpr[4], /* a0/arg0 */ + env->active_tc.gpr[5], /* a1/arg1 */ + env->active_tc.gpr[6], /* a2/arg2 */ + env->active_tc.gpr[7], /* a3/arg3 */ + env->active_tc.gpr[12],/* t4/arg4 */ + env->active_tc.gpr[13],/* t5/arg5 */ + env->active_tc.gpr[14],/* t6/arg6 */ + env->active_tc.gpr[15] /* t7/arg7 */ + ); +#endif /* ! TARGET_MIPS64 */ + } + } +/* done_syscall: */ + if (-TARGET_QEMU_ESIGRETURN == ret) { + /* + * Returning from a successful sigreturn + * syscall. Avoid clobbering register state. + */ + break; + } + if ((unsigned int)ret >= (unsigned int)(-1133)) { + env->active_tc.gpr[7] = 1; + ret = -ret; + } else { + env->active_tc.gpr[7] = 0; + } + env->active_tc.gpr[2] = ret; /* v0 <- ret */ + break; + + case EXCP_TLBL: /* TLB miss on load */ + case EXCP_TLBS: /* TLB miss on store */ + case EXCP_AdEL: /* bad address on load */ + case EXCP_AdES: /* bad address on store */ + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; + /* XXX: check env->error_code */ + info.si_code = TARGET_SEGV_MAPERR; + info._sifields._sigfault._addr = env->CP0_BadVAddr; + queue_signal(env, info.si_signo, &info); + break; + + case EXCP_CpU: /* coprocessor unusable */ + case EXCP_RI: /* reserved instruction */ + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = 0; + queue_signal(env, info.si_signo, &info); + break; + + case EXCP_INTERRUPT: /* async interrupt */ + /* just indicate that signals should be handled asap */ + break; + + case EXCP_DEBUG: /* cpu stopped after a breakpoint */ + { + 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(env, info.si_signo, &info); + } + } + break; + + case EXCP_SC: + if (do_store_exclusive(env)) { + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; + info.si_code = TARGET_SEGV_MAPERR; + info._sifields._sigfault._addr = + env->active_tc.PC; + queue_signal(env, info.si_signo, &info); + } + break; + + default: + fprintf(stderr, "qemu: unhandled CPU exception " + "0x%x - aborting\n", trapnr); + cpu_dump_state(env, stderr, fprintf, 0); + abort(); + } + process_pending_signals(env); + } +} +#endif /* defined(TARGET_MIPS) */ + #ifdef TARGET_SPARC #define SPARC64_STACK_BIAS 2047 @@ -969,6 +1207,15 @@ static void usage(void) THREAD CPUArchState *thread_env; +void stop_all_tasks(void) +{ + /* + * We trust when using NPTL (pthreads) start_exclusive() handles thread + * stopping correctly. + */ + start_exclusive(); +} + /* Assumes contents are already zeroed. */ void init_task_state(TaskState *ts) { @@ -990,6 +1237,7 @@ int main(int argc, char **argv) const char *log_mask = NULL; struct target_pt_regs regs1, *regs = ®s1; struct image_info info1, *info = &info1; + struct bsd_binprm bprm; TaskState ts1, *ts = &ts1; CPUArchState *env; int optind; @@ -997,7 +1245,11 @@ int main(int argc, char **argv) int gdbstub_port = 0; char **target_environ, **wrk; envlist_t *envlist = NULL; +#ifdef __FreeBSD__ + bsd_type = target_freebsd; +#else bsd_type = target_openbsd; +#endif if (argc <= 1) usage(); @@ -1141,6 +1393,8 @@ int main(int argc, char **argv) /* Zero out image_info */ memset(info, 0, sizeof(struct image_info)); + memset(&bprm, 0, sizeof(bprm)); + /* Scan interp_prefix dir for replacement files. */ init_paths(interp_prefix); @@ -1151,6 +1405,12 @@ int main(int argc, char **argv) #else cpu_model = "qemu32"; #endif +#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64) +#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) + cpu_model = "20Kc"; +#else + cpu_model = "24Kf"; +#endif #elif defined(TARGET_SPARC) #ifdef TARGET_SPARC64 cpu_model = "TI UltraSparc II"; @@ -1211,7 +1471,8 @@ int main(int argc, char **argv) } #endif /* CONFIG_USE_GUEST_BASE */ - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { + if (loader_exec(filename, argv+optind, target_environ, regs, info, + &bprm)!= 0) { printf("Error loading %s\n", filename); _exit(1); } @@ -1256,6 +1517,7 @@ int main(int argc, char **argv) memset(ts, 0, sizeof(TaskState)); init_task_state(ts); ts->info = info; + ts->bprm = &bprm; env->opaque = ts; #if defined(TARGET_I386) @@ -1394,6 +1656,20 @@ int main(int argc, char **argv) env->regs[i] = regs->uregs[i]; } } +#elif defined(TARGET_MIPS) + { + int i; + for(i = 0; i < 32; i++) { + env->active_tc.gpr[i] = regs->regs[i]; + } + env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; + if (regs->cp0_epc & 1) { + env->hflags |= MIPS_HFLAG_M16; + } +#if defined(TARGET_MIPS64) + env->hflags |= MIPS_HFLAG_UX; +#endif + } #else #error unsupported target CPU #endif diff --git a/work/qemu-1.2.0/bsd-user/mips/syscall.h b/work/qemu-1.2.0/bsd-user/mips/syscall.h new file mode 100644 index 0000000..8923556 --- /dev/null +++ b/work/qemu-1.2.0/bsd-user/mips/syscall.h @@ -0,0 +1,21 @@ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct target_pt_regs { + /* Pad bytes for argument save space on the stack. */ + abi_ulong pad0[6]; + + /* Saved main processor registers. */ + abi_ulong regs[32]; + + /* Saved special registers. */ + abi_ulong cp0_status; + abi_ulong lo; + abi_ulong hi; + abi_ulong cp0_badvaddr; + abi_ulong cp0_cause; + abi_ulong cp0_epc; +}; + +#define UNAME_MACHINE "mips" diff --git a/work/qemu-1.2.0/bsd-user/mips/target_signal.h b/work/qemu-1.2.0/bsd-user/mips/target_signal.h new file mode 100644 index 0000000..6e1dc8b --- /dev/null +++ b/work/qemu-1.2.0/bsd-user/mips/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { + abi_long ss_sp; + abi_ulong ss_size; + abi_long ss_flags; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) +{ + return state->active_tc.gpr[29]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/work/qemu-1.2.0/bsd-user/mips64/syscall.h b/work/qemu-1.2.0/bsd-user/mips64/syscall.h new file mode 100644 index 0000000..fca3634 --- /dev/null +++ b/work/qemu-1.2.0/bsd-user/mips64/syscall.h @@ -0,0 +1,21 @@ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct target_pt_regs { + /* Saved main processor registers. */ + abi_ulong regs[32]; + + /* Saved special registers. */ + abi_ulong cp0_status; + abi_ulong lo; + abi_ulong hi; + abi_ulong cp0_badvaddr; + abi_ulong cp0_cause; + abi_ulong cp0_epc; +}; + +/* Nasty hack: define a fake errno value for use by sigreturn. */ +#define TARGET_QEMU_ESIGRETURN 255 + +#define UNAME_MACHINE "mips64" diff --git a/work/qemu-1.2.0/bsd-user/mips64/target_signal.h b/work/qemu-1.2.0/bsd-user/mips64/target_signal.h new file mode 100644 index 0000000..2a3308e --- /dev/null +++ b/work/qemu-1.2.0/bsd-user/mips64/target_signal.h @@ -0,0 +1,31 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { + abi_long ss_sp; + abi_ulong ss_size; + abi_long ss_flags; +} target_stack_t; + + +#if 0 +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 +#endif + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) +{ + return state->active_tc.gpr[29]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/work/qemu-1.2.0/bsd-user/mmap.c b/work/qemu-1.2.0/bsd-user/mmap.c index 5d6cffc..71c57f8 100644 --- a/work/qemu-1.2.0/bsd-user/mmap.c +++ b/work/qemu-1.2.0/bsd-user/mmap.c @@ -493,7 +493,7 @@ int target_munmap(abi_ulong start, abi_ulong len) int prot, ret; #ifdef DEBUG_MMAP - printf("munmap: start=0x%lx len=0x%lx\n", start, len); + printf("munmap: start=0x" TARGET_FMT_lx " len=0x" TARGET_FMT_lx "\n", start, len); #endif if (start & ~TARGET_PAGE_MASK) return -EINVAL; diff --git a/work/qemu-1.2.0/bsd-user/qemu-types.h b/work/qemu-1.2.0/bsd-user/qemu-types.h index 1adda9f..5f4bb7a 100644 --- a/work/qemu-1.2.0/bsd-user/qemu-types.h +++ b/work/qemu-1.2.0/bsd-user/qemu-types.h @@ -9,6 +9,13 @@ typedef int32_t abi_long; #define TARGET_ABI_FMT_ld "%d" #define TARGET_ABI_FMT_lu "%u" #define TARGET_ABI_BITS 32 + +static inline abi_ulong +tswapal(abi_ulong v) +{ + return (tswap32(v)); +} + #else typedef target_ulong abi_ulong; typedef target_long abi_long; @@ -20,5 +27,11 @@ typedef target_long abi_long; #if TARGET_ABI_BITS == 32 #define TARGET_ABI32 1 #endif + +static inline abi_ulong tswapal(abi_ulong v) +{ + return (tswapl(v)); +} + #endif #endif diff --git a/work/qemu-1.2.0/bsd-user/qemu.h b/work/qemu-1.2.0/bsd-user/qemu.h index 2e55800..49c0dee 100644 --- a/work/qemu-1.2.0/bsd-user/qemu.h +++ b/work/qemu-1.2.0/bsd-user/qemu.h @@ -61,7 +61,7 @@ struct image_info { struct sigqueue { struct sigqueue *next; - //target_siginfo_t info; + target_siginfo_t info; }; struct emulated_sigtable { @@ -88,6 +88,7 @@ typedef struct TaskState { uint32_t stack_base; #endif struct image_info *info; + struct bsd_binprm *bprm; struct emulated_sigtable sigtab[TARGET_NSIG]; struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ @@ -98,6 +99,8 @@ typedef struct TaskState { } __attribute__((aligned(16))) TaskState; void init_task_state(TaskState *ts); +void task_settid(TaskState *); +void stop_all_tasks(void); extern const char *qemu_uname_release; #if defined(CONFIG_USE_GUEST_BASE) extern unsigned long mmap_min_addr; @@ -115,7 +118,7 @@ extern unsigned long mmap_min_addr; * This structure is used to hold the arguments that are * used when loading binaries. */ -struct linux_binprm { +struct bsd_binprm { char buf[128]; void *page[MAX_ARG_PAGES]; abi_ulong p; @@ -125,17 +128,19 @@ struct linux_binprm { char **argv; char **envp; char * filename; /* Name of binary */ + int (*core_dump)(int, const CPUArchState *); /* coredump routine */ }; void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); int loader_exec(const char * filename, char ** argv, char ** envp, - struct target_pt_regs * regs, struct image_info *infop); + struct target_pt_regs * regs, struct image_info *infop, + struct bsd_binprm *); -int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, +int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs, struct image_info * info); -int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, +int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs, struct image_info * info); abi_long memcpy_to_target(abi_ulong dest, const void *src, @@ -184,9 +189,9 @@ extern int do_strace; /* signal.c */ void process_pending_signals(CPUArchState *cpu_env); void signal_init(void); -//int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info); -//void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); -//void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info); +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); long do_sigreturn(CPUArchState *env); long do_rt_sigreturn(CPUArchState *env); abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); diff --git a/work/qemu-1.2.0/bsd-user/signal.c b/work/qemu-1.2.0/bsd-user/signal.c index 445f69e..ec4a702 100644 --- a/work/qemu-1.2.0/bsd-user/signal.c +++ b/work/qemu-1.2.0/bsd-user/signal.c @@ -16,6 +16,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ +#include +#include +#include + #include #include #include @@ -29,10 +33,584 @@ //#define DEBUG_SIGNAL -void signal_init(void) +#ifndef _NSIG +#define _NSIG 128 +#endif + +static uint8_t host_to_target_signal_table[_NSIG] = { + [SIGHUP] = TARGET_SIGHUP, + [SIGINT] = TARGET_SIGINT, + [SIGQUIT] = TARGET_SIGQUIT, + [SIGILL] = TARGET_SIGILL, + [SIGTRAP] = TARGET_SIGTRAP, + [SIGABRT] = TARGET_SIGABRT, + /* [SIGIOT] = TARGET_SIGIOT, */ + [SIGEMT] = TARGET_SIGEMT, + [SIGFPE] = TARGET_SIGFPE, + [SIGKILL] = TARGET_SIGKILL, + [SIGBUS] = TARGET_SIGBUS, + [SIGSEGV] = TARGET_SIGSEGV, + [SIGSYS] = TARGET_SIGSYS, + [SIGPIPE] = TARGET_SIGPIPE, + [SIGALRM] = TARGET_SIGALRM, + [SIGTERM] = TARGET_SIGTERM, + [SIGURG] = TARGET_SIGURG, + [SIGSTOP] = TARGET_SIGSTOP, + [SIGTSTP] = TARGET_SIGTSTP, + [SIGCONT] = TARGET_SIGCONT, + [SIGCHLD] = TARGET_SIGCHLD, + [SIGTTIN] = TARGET_SIGTTIN, + [SIGTTOU] = TARGET_SIGTTOU, + [SIGIO] = TARGET_SIGIO, + [SIGXCPU] = TARGET_SIGXCPU, + [SIGXFSZ] = TARGET_SIGXFSZ, + [SIGVTALRM] = TARGET_SIGALRM, + [SIGPROF] = TARGET_SIGPROF, + [SIGWINCH] = TARGET_SIGWINCH, + [SIGINFO] = TARGET_SIGINFO, + [SIGUSR1] = TARGET_SIGUSR1, + [SIGUSR2] = TARGET_SIGUSR2, +#ifdef SIGTHR + [SIGTHR] = TARGET_SIGTHR, +#endif + /* [SIGLWP] = TARGET_SIGLWP, */ +#ifdef SIGLIBRT + [SIGLIBRT] = TARGET_SIGLIBRT, +#endif + + /* + * The following signals stay the same. + * Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with + * host libpthread signals. This assumes no one actually uses + * SIGRTMAX. To fix this properly we need to manual signal delivery + * multiplexed over a single host signal. + */ + [SIGRTMIN] = SIGRTMAX, + [SIGRTMAX] = SIGRTMIN, +}; + +static uint8_t target_to_host_signal_table[_NSIG]; + +static struct target_sigaction sigact_table[TARGET_NSIG]; + +static void host_signal_handler(int host_signum, siginfo_t *info, void *puc); +static int host_to_target_signal(int sig); +static int target_to_host_signal(int sig); + +static int +host_to_target_signal(int sig) +{ + + if (sig >= _NSIG) + return (sig); + return (host_to_target_signal_table[sig]); +} + +static int +target_to_host_signal(int sig) +{ + + if (sig >= _NSIG) + return (sig); + return (target_to_host_signal_table[sig]); +} + +static inline void +target_sigemptyset(target_sigset_t *set) +{ + memset(set, 0, sizeof(*set)); +} + +static inline void +target_sigaddset(target_sigset_t *set, int signum) +{ + signum--; + abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW); + set->sig[signum / TARGET_NSIG_BPW] |= mask; +} + +static inline int +target_sigismember(const target_sigset_t *set, int signum) +{ + signum--; + abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW); + return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0); +} + +static void +host_to_target_sigset_internal(target_sigset_t *d, const sigset_t *s) +{ + int i; + + target_sigemptyset(d); + for (i = 1; i <= TARGET_NSIG; i++) { + if (sigismember(s, i)) { + target_sigaddset(d, host_to_target_signal(i)); + } + } +} + +void +host_to_target_sigset(target_sigset_t *d, const sigset_t *s) +{ + target_sigset_t d1; + int i; + + host_to_target_sigset_internal(&d1, s); + for(i = 0;i < TARGET_NSIG_WORDS; i++) + d->sig[i] = tswapal(d1.sig[i]); +} + +static void +target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) +{ + int i; + + sigemptyset(d); + for (i = 1; i <= TARGET_NSIG; i++) { + if (target_sigismember(s, i)) { + sigaddset(d, target_to_host_signal(i)); + } + } +} + +void +target_to_host_sigset(sigset_t *d, const target_sigset_t *s) { + target_sigset_t s1; + int i; + + for(i = 0; i < TARGET_NSIG_WORDS; i++) + s1.sig[i] = tswapal(s->sig[i]); + target_to_host_sigset_internal(d, &s1); +} + +/* Siginfo conversion. */ +static inline void +host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info) +{ + int sig; + + sig = host_to_target_signal(info->si_signo); + tinfo->si_signo = sig; + tinfo->si_errno = 0; + tinfo->si_code = info->si_code; + if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig || + SIGBUS == sig || SIGTRAP == sig) { + /* + * Should never come here but who knows. The information for + * the target is irrelevant. + */ + tinfo->_sifields._sigfault._addr = 0; +#if 0 + } else if (SIGIO == sig) { + tinfo->_sifields._sigpoll._fd = info->si_fd; +#endif + } else if (sig >= TARGET_SIGRTMIN) { + tinfo->_sifields._rt._pid = info->si_pid; + tinfo->_sifields._rt._uid = info->si_uid; + /* XXX: potential problem if 64 bit */ + tinfo->_sifields._rt._sigval.sival_ptr = + (abi_ulong)(unsigned long)info->si_value.sival_ptr; + } } -void process_pending_signals(CPUArchState *cpu_env) +/* Returns 1 if given signal should dump core if not handled. */ +static int +core_dump_signal(int sig) { + switch (sig) { + case TARGET_SIGABRT: + case TARGET_SIGFPE: + case TARGET_SIGILL: + case TARGET_SIGQUIT: + case TARGET_SIGSEGV: + case TARGET_SIGTRAP: + case TARGET_SIGBUS: + return (1); + default: + return (0); + } +} + +/* Signal queue handling. */ +static inline struct sigqueue * +alloc_sigqueue(CPUArchState *env) +{ + TaskState *ts = env->opaque; + struct sigqueue *q = ts->first_free; + + if (!q) + return (NULL); + ts->first_free = q->next; + return (q); +} + +static inline void +free_sigqueue(CPUArchState *env, struct sigqueue *q) +{ + + TaskState *ts = env->opaque; + q->next = ts->first_free; + ts->first_free = q; +} + +/* Abort execution with signal. */ +static void QEMU_NORETURN +force_sig(int target_sig) +{ + TaskState *ts = (TaskState *)thread_env->opaque; + int host_sig, core_dumped = 0; + struct sigaction act; + + host_sig = target_to_host_signal(target_sig); + gdb_signalled(thread_env, target_sig); + + /* Dump core if supported by target binary format */ + if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) { + stop_all_tasks(); + core_dumped = + ((*ts->bprm->core_dump)(target_sig, thread_env) == 0); + } + if (core_dumped) { + struct rlimit nodump; + + /* + * We already dumped the core of target process, we don't want + * a coredump of qemu itself. + */ + getrlimit(RLIMIT_CORE, &nodump); + nodump.rlim_cur = 0; + (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) " + "- %s\n", target_sig, strsignal(host_sig), "core dumped"); + } + + /* + * The proper exit code for dying from an uncaught signal is + * -. The kernel doesn't allow exit() or _exit() to pass + * a negative value. To get the proper exit code we need to + * actually die from an uncaught signal. Here the default signal + * handler is installed, we send ourself a signal and we wait for + * it to arrive. + */ + sigfillset(&act.sa_mask); + act.sa_handler = SIG_DFL; + sigaction(host_sig, &act, NULL); + + if (raise(host_sig) != 0) + kill(getpid(), host_sig); + + /* + * Make sure the signal isn't masked (just reuse the mask inside + * of act). + */ + sigdelset(&act.sa_mask, host_sig); + sigsuspend(&act.sa_mask); + + /* unreachable */ + abort(); +} + +/* + * Queue a signal so that it will be send to the virtual CPU as soon as + * possible. + */ +int +queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) +{ + TaskState *ts = env->opaque; + struct emulated_sigtable *k; + struct sigqueue *q, **pq; + abi_ulong handler; + int queue; + +#ifdef DEBUG_SIGNAL + fprintf(stderr, "queue_signal: sig=%d\n", sig); +#endif + k = &ts->sigtab[sig - 1]; + queue = gdb_queuesig (); + handler = sigact_table[sig - 1]._sa_handler; + if (!queue && TARGET_SIG_DFL == handler) { + if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || + sig == TARGET_SIGTTOU) { + kill(getpid(), SIGSTOP); + return (0); + } else + if (sig != TARGET_SIGCHLD && + sig != TARGET_SIGURG && + sig != TARGET_SIGWINCH && + sig != TARGET_SIGCONT) { + force_sig(sig); + } else { + return (0); /* The signal was ignored. */ + } + } else if (!queue && TARGET_SIG_IGN == handler) { + return (0); /* The signal was ignored. */ + } else if (!queue && TARGET_SIG_ERR == handler) { + force_sig(sig); + } else if (!queue && TARGET_SIG_ERR == handler) { + force_sig(sig); + } else { + pq = &k->first; + if (sig < TARGET_SIGRTMIN) { + /* + * If non real time signal then queue exactly one + * signal. + */ + if (!k->pending) + q = &k->info; + else + return (0); + } else { + if (!k->pending) { + /* first signal */ + q = &k->info; + } else { + q = alloc_sigqueue(env); + if (!q) + return (-EAGAIN); + while (*pq != NULL) + pq = &(*pq)->next; + } + } + *pq = q; + q->info = *info; + q->next = NULL; + k->pending = 1; + /* Signal that a new signal is pending. */ + ts->signal_pending = 1; + return (1); /* Indicates that the signal was queued. */ + } +} + +static void +host_signal_handler(int host_signum, siginfo_t *info, void *puc) +{ + int sig; + target_siginfo_t tinfo; + + /* + * The CPU emulator uses some host signal to detect exceptions so + * we forward to it some signals. + */ + if ((host_signum == SIGSEGV || host_signum == SIGBUS) && + info->si_code > 0) { + if (cpu_signal_handler(host_signum, info, puc)) + return; + } + + /* Get the target signal number. */ + sig = host_to_target_signal(host_signum); + if (sig < 1 || sig > TARGET_NSIG) + return; +#ifdef DEBUG_SIGNAL + fprintf(stderr, "qemu: got signal %d\n", sig); +#endif + host_to_target_siginfo_noswap(&tinfo, info); + if (queue_signal(thread_env, sig, &tinfo) == 1) { + /* Interrupt the virtual CPU as soon as possible. */ + cpu_exit(thread_env); + } +} + +static void +setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, + CPUArchState *env) +{ + fprintf(stderr, "setup_frame: not implemented\n"); +} + +static void +setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env) +{ + fprintf(stderr, "setup_rt_frame: not implemented\n"); +} + +long +do_sigreturn(CPUArchState *env) +{ + fprintf(stderr,"do_sigreturn: not implemented\n"); + return (-TARGET_ENOSYS); +} + +long +do_rt_sigreturn(CPUArchState *env) +{ + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); + return (-TARGET_ENOSYS); +} + + +static int +fatal_signal(int sig) +{ + + switch (sig) { + case TARGET_SIGCHLD: + case TARGET_SIGURG: + case TARGET_SIGWINCH: + /* Ignored by default. */ + return (0); + case TARGET_SIGCONT: + case TARGET_SIGSTOP: + case TARGET_SIGTSTP: + case TARGET_SIGTTIN: + case TARGET_SIGTTOU: + /* Job control signals. */ + return (0); + default: + return (1); + } +} + +void +signal_init(void) +{ + struct sigaction act; + struct sigaction oact; + int i, j; + int host_sig; + + /* Generate the signal conversion tables. */ + for(i = 1; i < _NSIG; i++) { + if (host_to_target_signal_table[i] == 0) + host_to_target_signal_table[i] = i; + } + for(i = 1; i < _NSIG; i++) { + j = host_to_target_signal_table[i]; + target_to_host_signal_table[j] = i; + } + + /* + * Set all host signal handlers. ALL signals are blocked during the + * handlers to serialize them. + */ + memset(sigact_table, 0, sizeof(sigact_table)); + + sigfillset(&act.sa_mask); + act.sa_sigaction = host_signal_handler; + + for (i = 1; i <= TARGET_NSIG; i++) { + host_sig = target_to_host_signal(i); + sigaction(host_sig, NULL, &oact); + if (oact.sa_sigaction == (void *)SIG_IGN) { + sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN; + } else if (oact.sa_sigaction == (void *)SIG_DFL) { + sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL; + } + /* + * If there's already a handler installed then something has + * gone horribly wrong, so don't even try to handle that case. + * Install some handlers for our own use. We need at least + * SIGSEGV and SIGBUS, to detect exceptions. We can not just + * trap all signals because it affects syscall interrupt + * behavior. But do trap all default-fatal signals. + */ + if (fatal_signal(i)) + sigaction(host_sig, &act, NULL); + } +} + +void +process_pending_signals(CPUArchState *cpu_env) +{ + int sig; + abi_ulong handler; + sigset_t set, old_set; + target_sigset_t target_old_set; + struct emulated_sigtable *k; + struct target_sigaction *sa; + struct sigqueue *q; + TaskState *ts = cpu_env->opaque; + + if (!ts->signal_pending) + return; + + /* FIXME: This is not threadsafe. */ + k = ts->sigtab; + for(sig = 1; sig <= TARGET_NSIG; sig++) { + if (k->pending) + goto handle_signal; + k++; + } + + /* If no signal is pending then just return. */ + ts->signal_pending = 0; + return; + +handle_signal: +#ifdef DEBUG_SIGNAL + fprintf(stderr, "qemu: process signal %d\n", sig); +#endif + + /* Dequeue signal. */ + q = k->first; + k->first = q->next; + if (!k->first) + k->pending = 0; + + sig = gdb_handlesig (cpu_env, sig); + if (!sig) { + sa = NULL; + handler = TARGET_SIG_IGN; + } else { + sa = &sigact_table[sig - 1]; + handler = sa->_sa_handler; + } + + if (handler == TARGET_SIG_DFL) { + /* + * default handler : ignore some signal. The other are job + * control or fatal. + */ + if (TARGET_SIGTSTP == sig || TARGET_SIGTTIN == sig || + TARGET_SIGTTOU == sig) { + kill(getpid(),SIGSTOP); + } else if (TARGET_SIGCHLD != sig && TARGET_SIGURG != sig && + TARGET_SIGWINCH != sig && TARGET_SIGCONT != sig) { + force_sig(sig); + } + } else if (TARGET_SIG_IGN == handler) { + /* ignore sig */ + } else if (TARGET_SIG_ERR == handler) { + /* compute the blocked signals during the handler execution */ + target_to_host_sigset(&set, &sa->sa_mask); + /* + * SA_NODEFER indicates that the current signal should not be + * blocked during the handler. + */ + if (!(sa->sa_flags & TARGET_SA_NODEFER)) + sigaddset(&set, target_to_host_signal(sig)); + + /* block signals in the handler */ + sigprocmask(SIG_BLOCK, &set, &old_set); + + /* + * Save the previous blocked signal state to restore it at the + * end of the signal execution (see do_sigreturn). + */ + host_to_target_sigset_internal(&target_old_set, &old_set); + +#if 0 +#if defined(TARGET_I386) && !defined(TARGET_X86_64) + /* if the CPU is in VM86 mode, we restore the 32 bit values */ + { + CPUX86State *env = cpu_env; + if (env->eflags & VM_MASK) + save_v86_state(env); + } +#endif +#endif + /* prepare the stack frame of the virtual CPU */ + if (sa->sa_flags & TARGET_SA_SIGINFO) + setup_rt_frame(sig, sa, &q->info, &target_old_set, + cpu_env); + else + setup_frame(sig, sa, &target_old_set, cpu_env); + if (sa->sa_flags & TARGET_SA_RESETHAND) + sa->_sa_handler = TARGET_SIG_DFL; + } + if (q != &k->info) + free_sigqueue(cpu_env, q); } diff --git a/work/qemu-1.2.0/bsd-user/syscall.c b/work/qemu-1.2.0/bsd-user/syscall.c index 2a6fd8f..1a4f62e 100644 --- a/work/qemu-1.2.0/bsd-user/syscall.c +++ b/work/qemu-1.2.0/bsd-user/syscall.c @@ -169,6 +169,14 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) return -TARGET_EINVAL; } #endif + +#ifdef TARGET_MIPS +static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) +{ + return -TARGET_EINVAL; +} +#endif + #ifdef __FreeBSD__ /* * XXX this uses the undocumented oidfmt interface to find the kind of diff --git a/work/qemu-1.2.0/bsd-user/syscall_defs.h b/work/qemu-1.2.0/bsd-user/syscall_defs.h index 3df481e..45c5b40 100644 --- a/work/qemu-1.2.0/bsd-user/syscall_defs.h +++ b/work/qemu-1.2.0/bsd-user/syscall_defs.h @@ -37,8 +37,6 @@ * @(#)signal.h 8.2 (Berkeley) 1/21/94 */ -#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ - #define TARGET_SIGHUP 1 /* hangup */ #define TARGET_SIGINT 2 /* interrupt */ #define TARGET_SIGQUIT 3 /* quit */ @@ -71,14 +69,21 @@ #define TARGET_SIGINFO 29 /* information request */ #define TARGET_SIGUSR1 30 /* user defined signal 1 */ #define TARGET_SIGUSR2 31 /* user defined signal 2 */ +#define TARGET_SIGTHR 32 /* reserved by thread library */ +#define TARGET_SIGLWP SIGTHR /* compatibility */ +#define TARGET_SIGLIBRT 33 /* reserved by the real-time library */ +#define TARGET_SIGRTMIN 65 +#define TARGET_SIGRTMAX 126 +#define TARGET_QEMU_ESIGRETURN 255 /* fake errno value for use by sigreturn */ + /* * Language spec says we must list exactly one parameter, even though we * actually supply three. Ugh! */ -#define TARGET_SIG_DFL (void (*)(int))0 -#define TARGET_SIG_IGN (void (*)(int))1 -#define TARGET_SIG_ERR (void (*)(int))-1 +#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */ +#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ +#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ #define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */ #define TARGET_SA_RESTART 0x0002 /* restart system on signal return */ @@ -101,6 +106,23 @@ #define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */ #define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ +/* + * si_code values + * Digital reserves positive values for kernel-generated signals. + */ + +/* + * SIGSEGV si_codes + */ +#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */ +#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped + object */ +/* + * SIGTRAP si_codes + */ +#define TARGET_TRAP_BRKPT (1) /* process beakpoint */ +#define TARGET_TRAP_TRACE (2) /* process trace trap */ + #include "errno_defs.h" #include "freebsd/syscall_nr.h" @@ -112,6 +134,120 @@ struct target_iovec { abi_long iov_len; /* Number of bytes */ }; +typedef abi_long target_clock_t; + +#define TARGET_NSIG 128 +#define TARGET_NSIG_BPW TARGET_ABI_BITS +#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW) + +typedef struct { + abi_ulong sig[TARGET_NSIG_WORDS]; +} target_sigset_t; + +#ifdef BSWAP_NEEDED +static inline void +tswap_sigset(target_sigset_t *d, const target_sigset_t *s) +{ + int i; + + for(i = 0; i < TARGET_NSIG_WORDS; i++) + d->sig[i] = tswapal(s->sig[i]); +} +#else +static inline void +tswap_sigset(target_sigset_t *d, const target_sigset_t *s) +{ + *d = *s; +} +#endif + +static inline void +target_siginitset(target_sigset_t *d, abi_ulong set) +{ + int i; + + d->sig[0] = set; + for(i = 1; i < TARGET_NSIG_WORDS; i++) + d->sig[i] = 0; +} + +void host_to_target_sigset(target_sigset_t *d, const sigset_t *s); +void target_to_host_sigset(sigset_t *d, const target_sigset_t *s); +void host_to_target_old_sigset(abi_ulong *old_sigset, const sigset_t *sigset); +void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset); +struct target_sigaction; +int do_sigaction(int sig, const struct target_sigaction *act, + struct target_sigaction *oact); + + +struct target_sigaction { + abi_ulong _sa_handler; + abi_ulong sa_flags; + target_sigset_t sa_mask; +}; + +typedef union target_sigval { + int sival_int; + abi_ulong sival_ptr; +} target_sigval_t; + +#define TARGET_SI_MAX_SIZE 128 +#define TARGET_SI_PAD_SIZE ((TARGET_SI_MAX_SIZE/sizeof(int)) - 3) + +typedef struct target_siginfo { +#ifdef TARGET_MIPS + int si_signo; + int si_code; + int si_errno; +#else + int si_signo; + int si_errno; + int si_code; +#endif + union { + int _pad[TARGET_SI_PAD_SIZE]; + + /* kill() */ + struct { + pid_t _pid; /* sender's pid */ + uid_t _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + /* POSIX.1b signals */ + struct { + pid_t _pid; /* sender's pid */ + uid_t _uid; /* sender's uid */ + target_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + pid_t _pid; /* which child */ + uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + target_clock_t _utime; + target_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + abi_ulong _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} target_siginfo_t; + struct target_kevent { abi_ulong ident; short filter; diff --git a/work/qemu-1.2.0/configure b/work/qemu-1.2.0/configure index fa2d3c1..34eca43 100755 --- a/work/qemu-1.2.0/configure +++ b/work/qemu-1.2.0/configure @@ -1019,6 +1019,9 @@ sparc-bsd-user \ sparc64-bsd-user \ arm-bsd-user \ armeb-bsd-user \ +mips-bsd-user \ +mipsel-bsd-user \ +mips64-bsd-user \ " fi diff --git a/work/qemu-1.2.0/default-configs/mips-bsd-user.mak b/work/qemu-1.2.0/default-configs/mips-bsd-user.mak new file mode 100644 index 0000000..3fb129a --- /dev/null +++ b/work/qemu-1.2.0/default-configs/mips-bsd-user.mak @@ -0,0 +1 @@ +# Default configuration for mips-bsd-user diff --git a/work/qemu-1.2.0/default-configs/mips64-bsd-user.mak b/work/qemu-1.2.0/default-configs/mips64-bsd-user.mak new file mode 100644 index 0000000..d4e72a6 --- /dev/null +++ b/work/qemu-1.2.0/default-configs/mips64-bsd-user.mak @@ -0,0 +1 @@ +# Default configuration for mips64-bsd-user diff --git a/work/qemu-1.2.0/default-configs/mipsel-bsd-user.mak b/work/qemu-1.2.0/default-configs/mipsel-bsd-user.mak new file mode 100644 index 0000000..312b9d5 --- /dev/null +++ b/work/qemu-1.2.0/default-configs/mipsel-bsd-user.mak @@ -0,0 +1 @@ +# Default configuration for mipsel-bsd-user diff --git a/work/qemu-1.2.0/target-mips/mips-defs.h b/work/qemu-1.2.0/target-mips/mips-defs.h index bf094a3..030937c 100644 --- a/work/qemu-1.2.0/target-mips/mips-defs.h +++ b/work/qemu-1.2.0/target-mips/mips-defs.h @@ -10,8 +10,14 @@ #if defined(TARGET_MIPS64) #define TARGET_LONG_BITS 64 -#define TARGET_PHYS_ADDR_SPACE_BITS 36 -#define TARGET_VIRT_ADDR_SPACE_BITS 42 +//#define TARGET_PHYS_ADDR_SPACE_BITS 36 +#define TARGET_PHYS_ADDR_SPACE_BITS 59 +# ifdef TARGET_ABI32 +# define TARGET_VIRT_ADDR_SPACE_BITS 32 +# else +//# define TARGET_VIRT_ADDR_SPACE_BITS 42 +# define TARGET_VIRT_ADDR_SPACE_BITS 62 +# endif #else #define TARGET_LONG_BITS 32 #define TARGET_PHYS_ADDR_SPACE_BITS 36