Commit b779e29ed8919b18644b41bf581bdbcffdcb962e
1 parent
8dfbe4e8
microblaze: linux-user support.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Showing
7 changed files
with
474 additions
and
5 deletions
cpu-exec.c
| ... | ... | @@ -246,6 +246,7 @@ int cpu_exec(CPUState *env1) |
| 246 | 246 | #elif defined(TARGET_ALPHA) |
| 247 | 247 | #elif defined(TARGET_ARM) |
| 248 | 248 | #elif defined(TARGET_PPC) |
| 249 | +#elif defined(TARGET_MICROBLAZE) | |
| 249 | 250 | #elif defined(TARGET_MIPS) |
| 250 | 251 | #elif defined(TARGET_SH4) |
| 251 | 252 | #elif defined(TARGET_CRIS) |
| ... | ... | @@ -300,6 +301,8 @@ int cpu_exec(CPUState *env1) |
| 300 | 301 | env->old_exception = -1; |
| 301 | 302 | #elif defined(TARGET_PPC) |
| 302 | 303 | do_interrupt(env); |
| 304 | +#elif defined(TARGET_MICROBLAZE) | |
| 305 | + do_interrupt(env); | |
| 303 | 306 | #elif defined(TARGET_MIPS) |
| 304 | 307 | do_interrupt(env); |
| 305 | 308 | #elif defined(TARGET_SPARC) |
| ... | ... | @@ -367,7 +370,8 @@ int cpu_exec(CPUState *env1) |
| 367 | 370 | cpu_loop_exit(); |
| 368 | 371 | } |
| 369 | 372 | #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ |
| 370 | - defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) | |
| 373 | + defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ | |
| 374 | + defined(TARGET_MICROBLAZE) | |
| 371 | 375 | if (interrupt_request & CPU_INTERRUPT_HALT) { |
| 372 | 376 | env->interrupt_request &= ~CPU_INTERRUPT_HALT; |
| 373 | 377 | env->halted = 1; |
| ... | ... | @@ -436,6 +440,15 @@ int cpu_exec(CPUState *env1) |
| 436 | 440 | env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
| 437 | 441 | next_tb = 0; |
| 438 | 442 | } |
| 443 | +#elif defined(TARGET_MICROBLAZE) | |
| 444 | + if ((interrupt_request & CPU_INTERRUPT_HARD) | |
| 445 | + && (env->sregs[SR_MSR] & MSR_IE) | |
| 446 | + && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) | |
| 447 | + && !(env->iflags & (D_FLAG | IMM_FLAG))) { | |
| 448 | + env->exception_index = EXCP_IRQ; | |
| 449 | + do_interrupt(env); | |
| 450 | + next_tb = 0; | |
| 451 | + } | |
| 439 | 452 | #elif defined(TARGET_MIPS) |
| 440 | 453 | if ((interrupt_request & CPU_INTERRUPT_HARD) && |
| 441 | 454 | (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) && |
| ... | ... | @@ -565,6 +578,8 @@ int cpu_exec(CPUState *env1) |
| 565 | 578 | env->sr = (env->sr & 0xffe0) |
| 566 | 579 | | env->cc_dest | (env->cc_x << 4); |
| 567 | 580 | log_cpu_state(env, 0); |
| 581 | +#elif defined(TARGET_MICROBLAZE) | |
| 582 | + log_cpu_state(env, 0); | |
| 568 | 583 | #elif defined(TARGET_MIPS) |
| 569 | 584 | log_cpu_state(env, 0); |
| 570 | 585 | #elif defined(TARGET_SH4) |
| ... | ... | @@ -682,6 +697,7 @@ int cpu_exec(CPUState *env1) |
| 682 | 697 | env->cc_op = CC_OP_FLAGS; |
| 683 | 698 | env->sr = (env->sr & 0xffe0) |
| 684 | 699 | | env->cc_dest | (env->cc_x << 4); |
| 700 | +#elif defined(TARGET_MICROBLAZE) | |
| 685 | 701 | #elif defined(TARGET_MIPS) |
| 686 | 702 | #elif defined(TARGET_SH4) |
| 687 | 703 | #elif defined(TARGET_ALPHA) |
| ... | ... | @@ -1028,6 +1044,56 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 1028 | 1044 | return 1; |
| 1029 | 1045 | } |
| 1030 | 1046 | |
| 1047 | +#elif defined (TARGET_MICROBLAZE) | |
| 1048 | +static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | |
| 1049 | + int is_write, sigset_t *old_set, | |
| 1050 | + void *puc) | |
| 1051 | +{ | |
| 1052 | + TranslationBlock *tb; | |
| 1053 | + int ret; | |
| 1054 | + | |
| 1055 | + if (cpu_single_env) | |
| 1056 | + env = cpu_single_env; /* XXX: find a correct solution for multithread */ | |
| 1057 | +#if defined(DEBUG_SIGNAL) | |
| 1058 | + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", | |
| 1059 | + pc, address, is_write, *(unsigned long *)old_set); | |
| 1060 | +#endif | |
| 1061 | + /* XXX: locking issue */ | |
| 1062 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
| 1063 | + return 1; | |
| 1064 | + } | |
| 1065 | + | |
| 1066 | + /* see if it is an MMU fault */ | |
| 1067 | + ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); | |
| 1068 | + if (ret < 0) | |
| 1069 | + return 0; /* not an MMU fault */ | |
| 1070 | + if (ret == 0) | |
| 1071 | + return 1; /* the MMU fault was handled without causing real CPU fault */ | |
| 1072 | + | |
| 1073 | + /* now we have a real cpu fault */ | |
| 1074 | + tb = tb_find_pc(pc); | |
| 1075 | + if (tb) { | |
| 1076 | + /* the PC is inside the translated code. It means that we have | |
| 1077 | + a virtual CPU fault */ | |
| 1078 | + cpu_restore_state(tb, env, pc, puc); | |
| 1079 | + } | |
| 1080 | + if (ret == 1) { | |
| 1081 | +#if 0 | |
| 1082 | + printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", | |
| 1083 | + env->PC, env->error_code, tb); | |
| 1084 | +#endif | |
| 1085 | + /* we restore the process signal mask as the sigreturn should | |
| 1086 | + do it (XXX: use sigsetjmp) */ | |
| 1087 | + sigprocmask(SIG_SETMASK, old_set, NULL); | |
| 1088 | + cpu_loop_exit(); | |
| 1089 | + } else { | |
| 1090 | + /* activate soft MMU for this block */ | |
| 1091 | + cpu_resume_from_signal(env, puc); | |
| 1092 | + } | |
| 1093 | + /* never comes here */ | |
| 1094 | + return 1; | |
| 1095 | +} | |
| 1096 | + | |
| 1031 | 1097 | #elif defined (TARGET_SH4) |
| 1032 | 1098 | static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 1033 | 1099 | int is_write, sigset_t *old_set, | ... | ... |
elf.h
| ... | ... | @@ -119,6 +119,8 @@ typedef int64_t Elf64_Sxword; |
| 119 | 119 | */ |
| 120 | 120 | #define EM_S390_OLD 0xA390 |
| 121 | 121 | |
| 122 | +#define EM_XILINX_MICROBLAZE 0xBAAB | |
| 123 | + | |
| 122 | 124 | /* This is the info that is needed to parse the dynamic section of the file */ |
| 123 | 125 | #define DT_NULL 0 |
| 124 | 126 | #define DT_NEEDED 1 | ... | ... |
linux-user/elfload.c
| ... | ... | @@ -453,6 +453,28 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i |
| 453 | 453 | |
| 454 | 454 | #endif /* TARGET_MIPS */ |
| 455 | 455 | |
| 456 | +#ifdef TARGET_MICROBLAZE | |
| 457 | + | |
| 458 | +#define ELF_START_MMAP 0x80000000 | |
| 459 | + | |
| 460 | +#define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE ) | |
| 461 | + | |
| 462 | +#define ELF_CLASS ELFCLASS32 | |
| 463 | +#define ELF_DATA ELFDATA2MSB | |
| 464 | +#define ELF_ARCH EM_MIPS | |
| 465 | + | |
| 466 | +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) | |
| 467 | +{ | |
| 468 | + regs->pc = infop->entry; | |
| 469 | + regs->r1 = infop->start_stack; | |
| 470 | + | |
| 471 | +} | |
| 472 | + | |
| 473 | +#define USE_ELF_CORE_DUMP | |
| 474 | +#define ELF_EXEC_PAGESIZE 4096 | |
| 475 | + | |
| 476 | +#endif /* TARGET_MICROBLAZE */ | |
| 477 | + | |
| 456 | 478 | #ifdef TARGET_SH4 |
| 457 | 479 | |
| 458 | 480 | #define ELF_START_MMAP 0x80000000 | ... | ... |
linux-user/main.c
| ... | ... | @@ -2036,6 +2036,66 @@ void cpu_loop (CPUState *env) |
| 2036 | 2036 | } |
| 2037 | 2037 | #endif |
| 2038 | 2038 | |
| 2039 | +#ifdef TARGET_MICROBLAZE | |
| 2040 | +void cpu_loop (CPUState *env) | |
| 2041 | +{ | |
| 2042 | + int trapnr, ret; | |
| 2043 | + target_siginfo_t info; | |
| 2044 | + | |
| 2045 | + while (1) { | |
| 2046 | + trapnr = cpu_mb_exec (env); | |
| 2047 | + switch (trapnr) { | |
| 2048 | + case 0xaa: | |
| 2049 | + { | |
| 2050 | + info.si_signo = SIGSEGV; | |
| 2051 | + info.si_errno = 0; | |
| 2052 | + /* XXX: check env->error_code */ | |
| 2053 | + info.si_code = TARGET_SEGV_MAPERR; | |
| 2054 | + info._sifields._sigfault._addr = 0; | |
| 2055 | + queue_signal(env, info.si_signo, &info); | |
| 2056 | + } | |
| 2057 | + break; | |
| 2058 | + case EXCP_INTERRUPT: | |
| 2059 | + /* just indicate that signals should be handled asap */ | |
| 2060 | + break; | |
| 2061 | + case EXCP_BREAK: | |
| 2062 | + /* Return address is 4 bytes after the call. */ | |
| 2063 | + env->regs[14] += 4; | |
| 2064 | + ret = do_syscall(env, | |
| 2065 | + env->regs[12], | |
| 2066 | + env->regs[5], | |
| 2067 | + env->regs[6], | |
| 2068 | + env->regs[7], | |
| 2069 | + env->regs[8], | |
| 2070 | + env->regs[9], | |
| 2071 | + env->regs[10]); | |
| 2072 | + env->regs[3] = ret; | |
| 2073 | + env->sregs[SR_PC] = env->regs[14]; | |
| 2074 | + break; | |
| 2075 | + case EXCP_DEBUG: | |
| 2076 | + { | |
| 2077 | + int sig; | |
| 2078 | + | |
| 2079 | + sig = gdb_handlesig (env, TARGET_SIGTRAP); | |
| 2080 | + if (sig) | |
| 2081 | + { | |
| 2082 | + info.si_signo = sig; | |
| 2083 | + info.si_errno = 0; | |
| 2084 | + info.si_code = TARGET_TRAP_BRKPT; | |
| 2085 | + queue_signal(env, info.si_signo, &info); | |
| 2086 | + } | |
| 2087 | + } | |
| 2088 | + break; | |
| 2089 | + default: | |
| 2090 | + printf ("Unhandled trap: 0x%x\n", trapnr); | |
| 2091 | + cpu_dump_state(env, stderr, fprintf, 0); | |
| 2092 | + exit (1); | |
| 2093 | + } | |
| 2094 | + process_pending_signals (env); | |
| 2095 | + } | |
| 2096 | +} | |
| 2097 | +#endif | |
| 2098 | + | |
| 2039 | 2099 | #ifdef TARGET_M68K |
| 2040 | 2100 | |
| 2041 | 2101 | void cpu_loop(CPUM68KState *env) |
| ... | ... | @@ -2698,6 +2758,42 @@ int main(int argc, char **argv, char **envp) |
| 2698 | 2758 | env->sr = regs->sr; |
| 2699 | 2759 | ts->sim_syscalls = 1; |
| 2700 | 2760 | } |
| 2761 | +#elif defined(TARGET_MICROBLAZE) | |
| 2762 | + { | |
| 2763 | + env->regs[0] = regs->r0; | |
| 2764 | + env->regs[1] = regs->r1; | |
| 2765 | + env->regs[2] = regs->r2; | |
| 2766 | + env->regs[3] = regs->r3; | |
| 2767 | + env->regs[4] = regs->r4; | |
| 2768 | + env->regs[5] = regs->r5; | |
| 2769 | + env->regs[6] = regs->r6; | |
| 2770 | + env->regs[7] = regs->r7; | |
| 2771 | + env->regs[8] = regs->r8; | |
| 2772 | + env->regs[9] = regs->r9; | |
| 2773 | + env->regs[10] = regs->r10; | |
| 2774 | + env->regs[11] = regs->r11; | |
| 2775 | + env->regs[12] = regs->r12; | |
| 2776 | + env->regs[13] = regs->r13; | |
| 2777 | + env->regs[14] = regs->r14; | |
| 2778 | + env->regs[15] = regs->r15; | |
| 2779 | + env->regs[16] = regs->r16; | |
| 2780 | + env->regs[17] = regs->r17; | |
| 2781 | + env->regs[18] = regs->r18; | |
| 2782 | + env->regs[19] = regs->r19; | |
| 2783 | + env->regs[20] = regs->r20; | |
| 2784 | + env->regs[21] = regs->r21; | |
| 2785 | + env->regs[22] = regs->r22; | |
| 2786 | + env->regs[23] = regs->r23; | |
| 2787 | + env->regs[24] = regs->r24; | |
| 2788 | + env->regs[25] = regs->r25; | |
| 2789 | + env->regs[26] = regs->r26; | |
| 2790 | + env->regs[27] = regs->r27; | |
| 2791 | + env->regs[28] = regs->r28; | |
| 2792 | + env->regs[29] = regs->r29; | |
| 2793 | + env->regs[30] = regs->r30; | |
| 2794 | + env->regs[31] = regs->r31; | |
| 2795 | + env->sregs[SR_PC] = regs->pc; | |
| 2796 | + } | |
| 2701 | 2797 | #elif defined(TARGET_MIPS) |
| 2702 | 2798 | { |
| 2703 | 2799 | int i; | ... | ... |
linux-user/signal.c
| ... | ... | @@ -3011,6 +3011,222 @@ badframe: |
| 3011 | 3011 | force_sig(TARGET_SIGSEGV); |
| 3012 | 3012 | return 0; |
| 3013 | 3013 | } |
| 3014 | +#elif defined(TARGET_MICROBLAZE) | |
| 3015 | + | |
| 3016 | +struct target_sigcontext { | |
| 3017 | + struct target_pt_regs regs; /* needs to be first */ | |
| 3018 | + uint32_t oldmask; | |
| 3019 | +}; | |
| 3020 | + | |
| 3021 | +/* Signal frames. */ | |
| 3022 | +struct target_signal_frame { | |
| 3023 | + struct target_sigcontext sc; | |
| 3024 | + uint32_t extramask[TARGET_NSIG_WORDS - 1]; | |
| 3025 | + uint32_t tramp[2]; | |
| 3026 | +}; | |
| 3027 | + | |
| 3028 | +struct rt_signal_frame { | |
| 3029 | + struct siginfo info; | |
| 3030 | + struct ucontext uc; | |
| 3031 | + uint32_t tramp[2]; | |
| 3032 | +}; | |
| 3033 | + | |
| 3034 | +static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env) | |
| 3035 | +{ | |
| 3036 | + __put_user(env->regs[0], &sc->regs.r0); | |
| 3037 | + __put_user(env->regs[1], &sc->regs.r1); | |
| 3038 | + __put_user(env->regs[2], &sc->regs.r2); | |
| 3039 | + __put_user(env->regs[3], &sc->regs.r3); | |
| 3040 | + __put_user(env->regs[4], &sc->regs.r4); | |
| 3041 | + __put_user(env->regs[5], &sc->regs.r5); | |
| 3042 | + __put_user(env->regs[6], &sc->regs.r6); | |
| 3043 | + __put_user(env->regs[7], &sc->regs.r7); | |
| 3044 | + __put_user(env->regs[8], &sc->regs.r8); | |
| 3045 | + __put_user(env->regs[9], &sc->regs.r9); | |
| 3046 | + __put_user(env->regs[10], &sc->regs.r10); | |
| 3047 | + __put_user(env->regs[11], &sc->regs.r11); | |
| 3048 | + __put_user(env->regs[12], &sc->regs.r12); | |
| 3049 | + __put_user(env->regs[13], &sc->regs.r13); | |
| 3050 | + __put_user(env->regs[14], &sc->regs.r14); | |
| 3051 | + __put_user(env->regs[15], &sc->regs.r15); | |
| 3052 | + __put_user(env->regs[16], &sc->regs.r16); | |
| 3053 | + __put_user(env->regs[17], &sc->regs.r17); | |
| 3054 | + __put_user(env->regs[18], &sc->regs.r18); | |
| 3055 | + __put_user(env->regs[19], &sc->regs.r19); | |
| 3056 | + __put_user(env->regs[20], &sc->regs.r20); | |
| 3057 | + __put_user(env->regs[21], &sc->regs.r21); | |
| 3058 | + __put_user(env->regs[22], &sc->regs.r22); | |
| 3059 | + __put_user(env->regs[23], &sc->regs.r23); | |
| 3060 | + __put_user(env->regs[24], &sc->regs.r24); | |
| 3061 | + __put_user(env->regs[25], &sc->regs.r25); | |
| 3062 | + __put_user(env->regs[26], &sc->regs.r26); | |
| 3063 | + __put_user(env->regs[27], &sc->regs.r27); | |
| 3064 | + __put_user(env->regs[28], &sc->regs.r28); | |
| 3065 | + __put_user(env->regs[29], &sc->regs.r29); | |
| 3066 | + __put_user(env->regs[30], &sc->regs.r30); | |
| 3067 | + __put_user(env->regs[31], &sc->regs.r31); | |
| 3068 | + __put_user(env->sregs[SR_PC], &sc->regs.pc); | |
| 3069 | +} | |
| 3070 | + | |
| 3071 | +static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env) | |
| 3072 | +{ | |
| 3073 | + __get_user(env->regs[0], &sc->regs.r0); | |
| 3074 | + __get_user(env->regs[1], &sc->regs.r1); | |
| 3075 | + __get_user(env->regs[2], &sc->regs.r2); | |
| 3076 | + __get_user(env->regs[3], &sc->regs.r3); | |
| 3077 | + __get_user(env->regs[4], &sc->regs.r4); | |
| 3078 | + __get_user(env->regs[5], &sc->regs.r5); | |
| 3079 | + __get_user(env->regs[6], &sc->regs.r6); | |
| 3080 | + __get_user(env->regs[7], &sc->regs.r7); | |
| 3081 | + __get_user(env->regs[8], &sc->regs.r8); | |
| 3082 | + __get_user(env->regs[9], &sc->regs.r9); | |
| 3083 | + __get_user(env->regs[10], &sc->regs.r10); | |
| 3084 | + __get_user(env->regs[11], &sc->regs.r11); | |
| 3085 | + __get_user(env->regs[12], &sc->regs.r12); | |
| 3086 | + __get_user(env->regs[13], &sc->regs.r13); | |
| 3087 | + __get_user(env->regs[14], &sc->regs.r14); | |
| 3088 | + __get_user(env->regs[15], &sc->regs.r15); | |
| 3089 | + __get_user(env->regs[16], &sc->regs.r16); | |
| 3090 | + __get_user(env->regs[17], &sc->regs.r17); | |
| 3091 | + __get_user(env->regs[18], &sc->regs.r18); | |
| 3092 | + __get_user(env->regs[19], &sc->regs.r19); | |
| 3093 | + __get_user(env->regs[20], &sc->regs.r20); | |
| 3094 | + __get_user(env->regs[21], &sc->regs.r21); | |
| 3095 | + __get_user(env->regs[22], &sc->regs.r22); | |
| 3096 | + __get_user(env->regs[23], &sc->regs.r23); | |
| 3097 | + __get_user(env->regs[24], &sc->regs.r24); | |
| 3098 | + __get_user(env->regs[25], &sc->regs.r25); | |
| 3099 | + __get_user(env->regs[26], &sc->regs.r26); | |
| 3100 | + __get_user(env->regs[27], &sc->regs.r27); | |
| 3101 | + __get_user(env->regs[28], &sc->regs.r28); | |
| 3102 | + __get_user(env->regs[29], &sc->regs.r29); | |
| 3103 | + __get_user(env->regs[30], &sc->regs.r30); | |
| 3104 | + __get_user(env->regs[31], &sc->regs.r31); | |
| 3105 | + __get_user(env->sregs[SR_PC], &sc->regs.pc); | |
| 3106 | +} | |
| 3107 | + | |
| 3108 | +static abi_ulong get_sigframe(struct target_sigaction *ka, | |
| 3109 | + CPUState *env, int frame_size) | |
| 3110 | +{ | |
| 3111 | + abi_ulong sp = env->regs[1]; | |
| 3112 | + | |
| 3113 | + if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp)) | |
| 3114 | + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; | |
| 3115 | + | |
| 3116 | + return ((sp - frame_size) & -8UL); | |
| 3117 | +} | |
| 3118 | + | |
| 3119 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 3120 | + target_sigset_t *set, CPUState *env) | |
| 3121 | +{ | |
| 3122 | + struct target_signal_frame *frame; | |
| 3123 | + abi_ulong frame_addr; | |
| 3124 | + int err = 0; | |
| 3125 | + int i; | |
| 3126 | + | |
| 3127 | + frame_addr = get_sigframe(ka, env, sizeof *frame); | |
| 3128 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
| 3129 | + goto badframe; | |
| 3130 | + | |
| 3131 | + /* Save the mask. */ | |
| 3132 | + err |= __put_user(set->sig[0], &frame->sc.oldmask); | |
| 3133 | + if (err) | |
| 3134 | + goto badframe; | |
| 3135 | + | |
| 3136 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 3137 | + if (__put_user(set->sig[i], &frame->extramask[i - 1])) | |
| 3138 | + goto badframe; | |
| 3139 | + } | |
| 3140 | + | |
| 3141 | + setup_sigcontext(&frame->sc, env); | |
| 3142 | + | |
| 3143 | + /* Set up to return from userspace. If provided, use a stub | |
| 3144 | + already in userspace. */ | |
| 3145 | + /* minus 8 is offset to cater for "rtsd r15,8" offset */ | |
| 3146 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 3147 | + env->regs[15] = ((unsigned long)ka->sa_restorer)-8; | |
| 3148 | + } else { | |
| 3149 | + uint32_t t; | |
| 3150 | + /* Note, these encodings are _big endian_! */ | |
| 3151 | + /* addi r12, r0, __NR_sigreturn */ | |
| 3152 | + t = 0x31800000UL | TARGET_NR_sigreturn; | |
| 3153 | + err |= __put_user(t, frame->tramp + 0); | |
| 3154 | + /* brki r14, 0x8 */ | |
| 3155 | + t = 0xb9cc0008UL; | |
| 3156 | + err |= __put_user(t, frame->tramp + 1); | |
| 3157 | + | |
| 3158 | + /* Return from sighandler will jump to the tramp. | |
| 3159 | + Negative 8 offset because return is rtsd r15, 8 */ | |
| 3160 | + env->regs[15] = ((unsigned long)frame->tramp) - 8; | |
| 3161 | + } | |
| 3162 | + | |
| 3163 | + if (err) | |
| 3164 | + goto badframe; | |
| 3165 | + | |
| 3166 | + /* Set up registers for signal handler */ | |
| 3167 | + env->regs[1] = (unsigned long) frame; | |
| 3168 | + /* Signal handler args: */ | |
| 3169 | + env->regs[5] = sig; /* Arg 0: signum */ | |
| 3170 | + env->regs[6] = (unsigned long) &frame->sc; /* arg 1: sigcontext */ | |
| 3171 | + | |
| 3172 | + /* Offset of 4 to handle microblaze rtid r14, 0 */ | |
| 3173 | + env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; | |
| 3174 | + | |
| 3175 | + unlock_user_struct(frame, frame_addr, 1); | |
| 3176 | + return; | |
| 3177 | + badframe: | |
| 3178 | + unlock_user_struct(frame, frame_addr, 1); | |
| 3179 | + force_sig(TARGET_SIGSEGV); | |
| 3180 | +} | |
| 3181 | + | |
| 3182 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 3183 | + target_siginfo_t *info, | |
| 3184 | + target_sigset_t *set, CPUState *env) | |
| 3185 | +{ | |
| 3186 | + fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n"); | |
| 3187 | +} | |
| 3188 | + | |
| 3189 | +long do_sigreturn(CPUState *env) | |
| 3190 | +{ | |
| 3191 | + struct target_signal_frame *frame; | |
| 3192 | + abi_ulong frame_addr; | |
| 3193 | + target_sigset_t target_set; | |
| 3194 | + sigset_t set; | |
| 3195 | + int i; | |
| 3196 | + | |
| 3197 | + frame_addr = env->regs[R_SP]; | |
| 3198 | + /* Make sure the guest isn't playing games. */ | |
| 3199 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) | |
| 3200 | + goto badframe; | |
| 3201 | + | |
| 3202 | + /* Restore blocked signals */ | |
| 3203 | + if (__get_user(target_set.sig[0], &frame->sc.oldmask)) | |
| 3204 | + goto badframe; | |
| 3205 | + for(i = 1; i < TARGET_NSIG_WORDS; i++) { | |
| 3206 | + if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) | |
| 3207 | + goto badframe; | |
| 3208 | + } | |
| 3209 | + target_to_host_sigset_internal(&set, &target_set); | |
| 3210 | + sigprocmask(SIG_SETMASK, &set, NULL); | |
| 3211 | + | |
| 3212 | + restore_sigcontext(&frame->sc, env); | |
| 3213 | + /* We got here through a sigreturn syscall, our path back is via an | |
| 3214 | + rtb insn so setup r14 for that. */ | |
| 3215 | + env->regs[14] = env->sregs[SR_PC]; | |
| 3216 | + | |
| 3217 | + unlock_user_struct(frame, frame_addr, 0); | |
| 3218 | + return env->regs[10]; | |
| 3219 | + badframe: | |
| 3220 | + unlock_user_struct(frame, frame_addr, 0); | |
| 3221 | + force_sig(TARGET_SIGSEGV); | |
| 3222 | +} | |
| 3223 | + | |
| 3224 | +long do_rt_sigreturn(CPUState *env) | |
| 3225 | +{ | |
| 3226 | + fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n"); | |
| 3227 | + return -TARGET_ENOSYS; | |
| 3228 | +} | |
| 3229 | + | |
| 3014 | 3230 | #elif defined(TARGET_CRIS) |
| 3015 | 3231 | |
| 3016 | 3232 | struct target_sigcontext { | ... | ... |
linux-user/syscall.c
| ... | ... | @@ -4854,7 +4854,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
| 4854 | 4854 | #endif |
| 4855 | 4855 | #ifdef TARGET_NR_mmap |
| 4856 | 4856 | case TARGET_NR_mmap: |
| 4857 | -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) | |
| 4857 | +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) | |
| 4858 | 4858 | { |
| 4859 | 4859 | abi_ulong *v; |
| 4860 | 4860 | abi_ulong v1, v2, v3, v4, v5, v6; | ... | ... |
linux-user/syscall_defs.h
| ... | ... | @@ -59,7 +59,8 @@ |
| 59 | 59 | #define TARGET_IOC_READ 2U |
| 60 | 60 | |
| 61 | 61 | #elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ |
| 62 | - defined(TARGET_SPARC) || defined(TARGET_MIPS) | |
| 62 | + defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) || \ | |
| 63 | + defined(TARGET_MIPS) | |
| 63 | 64 | |
| 64 | 65 | #define TARGET_IOC_SIZEBITS 13 |
| 65 | 66 | #define TARGET_IOC_DIRBITS 3 |
| ... | ... | @@ -286,7 +287,7 @@ struct target_sigaction; |
| 286 | 287 | int do_sigaction(int sig, const struct target_sigaction *act, |
| 287 | 288 | struct target_sigaction *oact); |
| 288 | 289 | |
| 289 | -#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) || defined(TARGET_CRIS) | |
| 290 | +#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) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) | |
| 290 | 291 | |
| 291 | 292 | #if defined(TARGET_SPARC) |
| 292 | 293 | #define TARGET_SA_NOCLDSTOP 8u |
| ... | ... | @@ -1170,6 +1171,54 @@ struct __attribute__((__packed__)) target_stat64 { |
| 1170 | 1171 | unsigned int __unused5; |
| 1171 | 1172 | }; |
| 1172 | 1173 | |
| 1174 | +#elif defined(TARGET_MICROBLAZE) | |
| 1175 | + | |
| 1176 | +struct target_stat { | |
| 1177 | + abi_ulong st_dev; | |
| 1178 | + abi_ulong st_ino; | |
| 1179 | + unsigned int st_mode; | |
| 1180 | + unsigned short st_nlink; | |
| 1181 | + unsigned int st_uid; | |
| 1182 | + unsigned int st_gid; | |
| 1183 | + abi_ulong st_rdev; | |
| 1184 | + abi_ulong st_size; | |
| 1185 | + abi_ulong st_blksize; | |
| 1186 | + abi_ulong st_blocks; | |
| 1187 | + abi_ulong target_st_atime; | |
| 1188 | + abi_ulong target_st_atime_nsec; | |
| 1189 | + abi_ulong target_st_mtime; | |
| 1190 | + abi_ulong target_st_mtime_nsec; | |
| 1191 | + abi_ulong target_st_ctime; | |
| 1192 | + abi_ulong target_st_ctime_nsec; | |
| 1193 | + abi_ulong __unused4; | |
| 1194 | + abi_ulong __unused5; | |
| 1195 | +}; | |
| 1196 | + | |
| 1197 | +/* FIXME: Microblaze no-mmu user-space has a difference stat64 layout... */ | |
| 1198 | +struct __attribute__((__packed__)) target_stat64 { | |
| 1199 | + uint64_t st_dev; | |
| 1200 | + uint64_t st_ino; | |
| 1201 | + uint32_t st_mode; | |
| 1202 | + uint32_t st_nlink; | |
| 1203 | + uint32_t st_uid; | |
| 1204 | + uint32_t st_gid; | |
| 1205 | + uint64_t st_rdev; | |
| 1206 | + uint32_t __pad2; | |
| 1207 | + | |
| 1208 | + int64_t st_size; | |
| 1209 | + int32_t st_blksize; | |
| 1210 | + int64_t st_blocks; /* Number 512-byte blocks allocated. */ | |
| 1211 | + | |
| 1212 | + int target_st_atime; | |
| 1213 | + unsigned int target_st_atime_nsec; | |
| 1214 | + int target_st_mtime; | |
| 1215 | + unsigned int target_st_mtime_nsec; | |
| 1216 | + int target_st_ctime; | |
| 1217 | + unsigned int target_st_ctime_nsec; | |
| 1218 | + uint32_t __unused4; | |
| 1219 | + uint32_t __unused5; | |
| 1220 | +}; | |
| 1221 | + | |
| 1173 | 1222 | #elif defined(TARGET_M68K) |
| 1174 | 1223 | |
| 1175 | 1224 | struct target_stat { |
| ... | ... | @@ -1719,6 +1768,24 @@ struct target_statfs64 { |
| 1719 | 1768 | #define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ |
| 1720 | 1769 | #define TARGET_O_LARGEFILE 0200000 |
| 1721 | 1770 | #define TARGET_O_DIRECT 0400000 /* direct disk access hint */ |
| 1771 | +#elif defined (TARGET_MICROBLAZE) | |
| 1772 | +#define TARGET_O_ACCMODE 0003 | |
| 1773 | +#define TARGET_O_RDONLY 00 | |
| 1774 | +#define TARGET_O_WRONLY 01 | |
| 1775 | +#define TARGET_O_RDWR 02 | |
| 1776 | +#define TARGET_O_CREAT 0100 /* not fcntl */ | |
| 1777 | +#define TARGET_O_EXCL 0200 /* not fcntl */ | |
| 1778 | +#define TARGET_O_NOCTTY 0400 /* not fcntl */ | |
| 1779 | +#define TARGET_O_TRUNC 01000 /* not fcntl */ | |
| 1780 | +#define TARGET_O_APPEND 02000 | |
| 1781 | +#define TARGET_O_NONBLOCK 04000 | |
| 1782 | +#define TARGET_O_NDELAY TARGET_O_NONBLOCK | |
| 1783 | +#define TARGET_O_SYNC 010000 | |
| 1784 | +#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */ | |
| 1785 | +#define TARGET_O_DIRECTORY 040000 /* must be a directory */ | |
| 1786 | +#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ | |
| 1787 | +#define TARGET_O_LARGEFILE 0200000 | |
| 1788 | +#define TARGET_O_DIRECT 0400000 /* direct disk access hint */ | |
| 1722 | 1789 | #elif defined (TARGET_SPARC) |
| 1723 | 1790 | #define TARGET_O_RDONLY 0x0000 |
| 1724 | 1791 | #define TARGET_O_WRONLY 0x0001 |
| ... | ... | @@ -1806,7 +1873,7 @@ struct target_flock { |
| 1806 | 1873 | struct target_flock64 { |
| 1807 | 1874 | short l_type; |
| 1808 | 1875 | short l_whence; |
| 1809 | -#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) | |
| 1876 | +#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined (TARGET_MICROBLAZE) | |
| 1810 | 1877 | int __pad; |
| 1811 | 1878 | #endif |
| 1812 | 1879 | unsigned long long l_start; | ... | ... |